26 #include <Classes.hpp>
27 #include <Controls.hpp>
28 #include <StdCtrls.hpp>
30 #include <Buttons.hpp>
31 #include <ExtCtrls.hpp>
33 #include <Dialogs.hpp>
34 #include <Graphics.hpp>
35 #include <ComCtrls.hpp>
52 #pragma package(smart_init)
62 TTrain::TTrain(
int Caller,
int RearStartElementIn,
int RearStartExitPosIn, AnsiString InputCode,
int StartSpeedIn,
int MassIn,
double MaxRunningSpeedIn,
63 double MaxBrakeRateIn,
double PowerAtRailIn,
TTrainMode TrainModeIn,
TTrainDataEntry *TrainDataEntryPtrIn,
int RepeatNumberIn,
int IncrementalMinutesIn,
64 int IncrementalDigitsIn,
int SignallerMaxSpeedIn) : RearStartElement(RearStartElementIn), RearStartExitPos(RearStartExitPosIn), HeadCode(InputCode),
65 StartSpeed(StartSpeedIn), Mass(MassIn), MaxRunningSpeed(MaxRunningSpeedIn), MaxBrakeRate(MaxBrakeRateIn), PowerAtRail(PowerAtRailIn),
66 TrainMode(TrainModeIn), TrainDataEntryPtr(TrainDataEntryPtrIn), RepeatNumber(RepeatNumberIn), IncrementalMinutes(IncrementalMinutesIn),
67 IncrementalDigits(IncrementalDigitsIn), SignallerMaxSpeed(SignallerMaxSpeedIn)
78 AnsiString(RearStartExitPosIn) +
"," + AnsiString(InputCode) +
"," + AnsiString(StartSpeedIn) +
"," + AnsiString(MassIn) +
"," +
79 AnsiString(TrainModeIn));
123 for(
int x = 0; x < 4; x++)
132 for(
int x = 0; x < 4; x++)
141 for(
int x = 0; x < 4; x++)
146 for(
int x = 0; x < 4; x++)
150 for(
int x = 0; x < 3; x++)
187 for(
int x = 0; x < 4; x++)
234 throw Exception(
"Error in attempting to delete FrontCodePtr");
238 for(
int x = 0; x < 4; x++)
242 throw Exception(
"Error in attempting to delete BackgroundPtr[" + AnsiString(x) +
"]");
247 for(
int x = 0; x < 4; x++)
251 throw Exception(
"Error in attempting to delete HeadCodeGrPtr[" + AnsiString(x) +
"]");
280 int NextElementPosition, NextEntryPos, ElementLength, SpeedLimit;
346 bool TempDerail =
false;
392 else if((NextElementPosition > -1) && (NextEntryPos > -1))
463 throw Exception(
"Error, LeadElement Exit Connection is NotSet");
473 for(
int x = 0; x < 4; x++)
480 for(
int x = 0; x < 4; x++)
723 if((random(RandRange)) == 0)
738 int LockedVectorNumber;
975 if(BufferLocation ==
"")
980 if((BufferLocation ==
"") || (BufferLocation != ExpectedLocation))
1042 int NextElementPosition, NextEntryPos;
1066 NextElementPosition = -1;
1069 if((NextElementPosition > -1) && (NextEntryPos > -1))
1188 AnsiString StationName;
1199 throw Exception(
"Error - Stopped at through station but neither lead nor mid elements have a name");
1212 if((NextElementPosition > -1) && (NextEntryPos > -1))
1325 if(TIFEntryPos == 0)
1361 if(NextElementPosition > -1)
1398 AnsiString Loc =
"";
1399 bool LocNamed =
false;
1428 Loc =
"outside railway";
1460 NextElementPosition = -1;
1471 if((NextElementPosition > -1) && (NextEntryPos > -1) && !
SPADFlag)
1489 if((NextElementPosition > -1) && (NextEntryPos > -1))
1527 FirstPair.second).
GetELink() == TempELink))
1532 SecondPair.second).
GetELink() == TempELink))
1546 FirstPair.second).
GetELink() == TempELink))
1551 SecondPair.second).
GetELink() == TempELink))
1565 FirstPair.second).
GetELink() == TempELink))
1570 SecondPair.second).
GetELink() == TempELink))
1600 ContinuationAutoSigEntry.
RouteNumber = RouteNumber;
1603 int NewLastElement = 0, NewLastExitPos = 0;
1621 if(NewLastElement == -1)
1624 throw Exception(
"Error, Connection = -1 in Continuation loop in UpdateTrain");
1627 if(NewLastExitPos == -1)
1629 throw Exception(
"Error, ConnLinkPos = -1 in Continuation loop in UpdateTrain");
1631 LastElement = NewLastElement;
1632 LastExitPos = NewLastExitPos;
1635 if(CumDistance < 1200)
1641 int FirstDistance = 0;
1642 if(CumDistance >= 1200)
1644 FirstDistance = 100;
1648 FirstDistance = 1200 - CumDistance;
1650 if(FirstDistance < 100)
1652 FirstDistance = 100;
1678 if(VectorIT->RouteNumber == RouteNumber)
1725 LockedVectorNumber)))
1884 for(
int x = 0; x < 4; x++)
1891 for(
int x = 0; x < 4; x++)
1917 if((LeadElementTrainID > -1) && (LeadElementTrainID !=
TrainID))
1922 if(OtherTrainEntryPos == -1)
1924 throw Exception(
"Error - OtherTrainEntryPos not set");
1943 int OtherTrainID = -1;
1944 if((MidExitLinkNum == 1) || (MidExitLinkNum == 3) || (MidExitLinkNum == 7) || (MidExitLinkNum == 9))
2035 bool StopRequired =
false;
2048 int NextElementEntryPos = -1;
2049 int NextElementExitPos = -1;
2050 bool TrainOnNextElement =
false;
2051 bool StopSignalAtNextElement =
false;
2052 if(ForwardConnection)
2060 StopSignalAtNextElement = ((NextTrackElement.
Config[NextElementExitPos] ==
Signal) && (NextTrackElement.
Attribute == 0));
2063 if(TrainAtStopLinkPos1 || TrainAtStopLinkPos2 || (ForwardConnection && (TrainOnNextElement || StopSignalAtNextElement)))
2118 throw Exception(
"Error, Straddle shouldn't be LeadMid prior to resetting at exit from UpdateTrain");
2331 if(Code.Length() != 4)
2335 for(
int x = 1; x < 5; x++)
2342 for(
int x = 0; x < 4; x++)
2506 throw Exception(
"Error in GetOffsetValues - Link value wrong");
2519 if((EntryLink == 1) || (EntryLink == 2) || (EntryLink == 4) || (EntryLink == 7))
2534 AnsiString(
VOffset) +
"," + AnsiString(Element) +
"," + AnsiString(EntryPos) +
"," +
HeadCode);
2543 TRect SourceRect, DestRect;
2545 DestRect.init(0, 0, 8, 8);
2548 Graphics::TBitmap *TempGraphic =
new Graphics::TBitmap;
2550 TempGraphic->PixelFormat = pf8bit;
2551 TempGraphic->Width = 16;
2552 TempGraphic->Height = 16;
2558 TempGraphic->Transparent =
true;
2562 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2563 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2569 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2577 else if(TempElement.
SpeedTag == 89)
2581 else if(TempElement.
SpeedTag == 90)
2585 else if(TempElement.
SpeedTag == 91)
2589 else if(TempElement.
SpeedTag == 92)
2593 else if(TempElement.
SpeedTag == 93)
2597 else if(TempElement.
SpeedTag == 94)
2601 else if(TempElement.
SpeedTag == 95)
2605 TempGraphic->Transparent =
true;
2609 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2610 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2612 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2619 for(
int x = 0; x < 40; x++)
2634 TempGraphic->Transparent =
true;
2638 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2639 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2641 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2655 TempGraphic->Transparent =
true;
2659 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2660 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2664 TempGraphic->Canvas->Draw(0, 0, TempElement.
GraphicPtr);
2667 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2672 TempGraphic->Transparent =
true;
2676 int BDVectorPos = -1;
2685 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2690 TempGraphic->Transparent =
true;
2694 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2695 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2697 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2703 TempGraphic->Transparent =
true;
2707 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2708 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2710 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2976 throw Exception(
"Error, same train on two different bridge tracks");
3022 AnsiString(EntryPos) +
"," +
HeadCode);
3039 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in SetTrainElementID");
3058 AnsiString(EntryPos) +
"," +
HeadCode);
3067 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in ResetTrainElementID");
3100 AnsiString(ElementEntryPos) +
"," + AnsiString(
HOffset) +
"," + AnsiString(
VOffset) +
"," + AnsiString(StraddleValue) +
"," +
HeadCode);
3101 int LockedVectorNumber;
3114 TRect SourceRect, DestRect;
3115 DestRect.init(0, 0, 8, 8);
3122 int FirstELink, SecondELink = -1;
3125 if(RoutePair2.first > -1)
3134 if(SecondELink == -1)
3136 throw Exception(
"Error - Second ELink should be set but isn't in PlotAlternativeTrackRouteGraphic [1]");
3141 throw Exception(
"Error - First & Second ELinks have same value in PlotAlternativeTrackRouteGraphic");
3151 Graphics::TBitmap *DestGraphic =
new Graphics::TBitmap;
3152 DestGraphic->PixelFormat = pf8bit;
3153 DestGraphic->Width = 8;
3154 DestGraphic->Height = 8;
3155 DestGraphic->Transparent =
true;
3158 DestGraphic->Canvas->CopyRect(DestRect, RouteElement.
GetRouteEXGraphicPtr()->Canvas, SourceRect);
3167 PrefDirElement, LockedVectorNumber))
3182 if(ElementEntryPos > 1)
3204 AnsiString(EntryPos) +
"," +
HeadCode);
3206 bool WrongRoute =
false;
3232 int LinkNumber = TrackElement.
Link[EntryPos];
3233 if((LinkNumber == 1) || (LinkNumber == 3) || (LinkNumber == 7) || (LinkNumber == 9))
3238 bool LogActionErrorCalled =
false;
3248 LogActionErrorCalled =
true;
3265 else if(LinkNumber == 3)
3273 LogActionErrorCalled =
true;
3290 else if(LinkNumber == 7)
3298 LogActionErrorCalled =
true;
3315 else if(LinkNumber == 9)
3323 LogActionErrorCalled =
true;
3355 else if((RouteElement.
GetELinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3360 else if((RouteElement.
GetELinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3370 else if((RouteElement.
GetXLinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3375 else if((RouteElement.
GetXLinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3384 throw Exception(
"Error, Element in route but no route found in CheckAndCancelRouteForWrongEndEntry");
3405 bool ColourError =
false, ColourError2 =
false;
3410 ColourError2 =
true;
3412 for(
int x = 0; x < 4; x++)
3417 ColourError2 =
true;
3423 "ERROR: Colour depth insufficient to display train colours properly. Please ensure that the 'safe' (web) palette of 256 colours can be displayed");
3427 for(
int x = 0; x < 4; x++)
3514 AnsiString(EntryPos) +
"," +
HeadCode);
3515 int EntryHalfLength, CurrentElementHalfLength, NextElementHalfLength, CumulativeLength = 0, CurrentTrackVectorPosition = TrackVectorPosition;
3516 int DistanceAtHalfBraking, DistanceAtThreeQuarterBraking, ExitPos, NextTrackVectorPosition, NextEntryPos;
3517 bool RedSignalFlag =
false, BuffersFlag =
false, StationFlag =
false, BuffersOrContinuationNowFlag =
false, ContinuationNextFlag =
false,
3518 TrainInFrontInSignallerModeFlag =
false;
3519 double LimitingSpeed, FrontElementMaxSpeed, MaxExitSpeedAtHalfBrakingSquared, MaxExitSpeedAtHalfBraking, NextSpeedLimit, TempBrakeRate;
3520 double ExitSpeedHalfSquared, ExitSpeedFullSquared;
3521 bool SignallerStopRequired =
false;
3532 if(CurrentTrackVectorPosition > -1)
3536 if((EntryPos == 0) || (EntryPos == 2))
3549 else if(EntryPos == 1)
3573 EntryHalfLength = CurrentElementHalfLength;
3578 throw Exception(
"Error - CurrentTrackVectorPosition < 0 in SetTrainMovementValues");
3582 throw Exception(
"Error - HalfLength or SpeedLimit < 0 in SetTrainMovementValues");
3629 FrontElementMaxSpeed = LimitingSpeed;
3659 double ExitSpeedAtMaxBraking;
3664 ExitSpeedAtMaxBraking = 0;
3674 if(ExitSpeedAtMaxBraking > LimitingSpeed)
3676 SpeedToUse = ExitSpeedAtMaxBraking;
3680 SpeedToUse = LimitingSpeed;
3695 RedSignalFlag =
false;
3696 BuffersFlag =
false;
3697 StationFlag =
false;
3698 BuffersOrContinuationNowFlag =
false;
3699 ContinuationNextFlag =
false;
3702 CumulativeLength += (2 * CurrentElementHalfLength);
3705 SignallerStopRequired =
true;
3727 bool StopRequired =
false;
3741 StationFlag =
false;
3747 BuffersOrContinuationNowFlag =
true;
3749 if(!BuffersOrContinuationNowFlag && !BuffersFlag && !StationFlag)
3753 if((EntryPos == 0) || (EntryPos == 2))
3775 if(NextTrackVectorPosition > -1)
3780 if((NextEntryPos == 0) || (NextEntryPos == 2))
3793 else if(NextEntryPos == 1)
3806 if(NextEntryPos > 1)
3820 throw Exception(
"Error - Trying to access NextTrackVectorPosition when none present in SetTrainMovementValues");
3832 RedSignalFlag =
true;
3854 TrainInFrontInSignallerModeFlag =
true;
3878 if(RedSignalFlag || BuffersFlag || StationFlag || TrainInFrontInSignallerModeFlag || SignallerStopRequired ||
StepForwardFlag)
3890 double MaxHalfSpeed;
3894 if(MaxHalfSpeedAtHalfBraking > FrontElementMaxSpeed)
3896 MaxHalfSpeed = FrontElementMaxSpeed;
3900 MaxHalfSpeed = MaxHalfSpeedAtHalfBraking;
3908 bool HalfSpeedLimited =
false;
3912 HalfSpeedLimited =
true;
3942 if(HalfSpeedLimited)
3967 if(SignallerStopRequired)
3983 int TempMaxExitSpeed;
3986 if(MaxExitSpeedAtHalfBrakingSquared < 10)
3988 MaxExitSpeedAtHalfBraking = 0;
3992 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
3996 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
3998 TempMaxExitSpeed = FrontElementMaxSpeed;
4002 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4014 if(ExitSpeedHalfSquared < 10)
4024 if(ExitSpeedFullSquared < 10)
4096 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4097 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4121 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4122 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4132 if(!BuffersOrContinuationNowFlag)
4134 if(NextSpeedLimit < LimitingSpeed)
4136 LimitingSpeed = NextSpeedLimit;
4140 int TempMaxExitSpeed;
4144 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4146 MaxExitSpeedAtHalfBraking = 0;
4150 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4152 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4154 TempMaxExitSpeed = FrontElementMaxSpeed;
4158 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4169 TempBrakeRate = ((
EntrySpeed *
EntrySpeed) - (LimitingSpeed * LimitingSpeed)) / 3.6 / 3.6 / 2 / CumulativeLength;
4182 if(!BuffersOrContinuationNowFlag)
4184 CurrentTrackVectorPosition = NextTrackVectorPosition;
4185 EntryPos = NextEntryPos;
4186 CurrentElementHalfLength = NextElementHalfLength;
4189 ContinuationNextFlag =
true;
4193 while(((CumulativeLength -
FrontElementLength) < DistanceAtHalfBraking) && ((!BuffersOrContinuationNowFlag && !ContinuationNextFlag) ||
4213 if(ExitSpeedHalfSquared < 10)
4223 if(ExitSpeedFullSquared < 10)
4286 double DeltaExitTimeToMaxInSecs;
4287 double DistanceToMax;
4296 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4298 DistanceToMax = EntryHalfLength;
4301 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4302 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4319 double DeltaExitTimeToMaxInSecs;
4320 double DistanceToMax;
4329 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4331 DistanceToMax = EntryHalfLength / 2;
4334 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4335 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4346 if(ExitSpeedHalfSquared < 10)
4356 if(ExitSpeedFullSquared < 10)
4375 if((EntryPos == 0) || (EntryPos == 2))
4397 if(NextTrackVectorPosition > -1)
4399 int NextElementLength;
4400 if(NextEntryPos > 1)
4408 double NextStoppingSpeed = sqrt(3.6 * 3.6 * 2 *
BrakeRate * NextElementLength);
4544 if((Ptr->Command ==
"cdt") || (Ptr->FormatType ==
Repeat))
4548 if((Ptr->ArrivalTime > TDateTime(-1)) && (Ptr->LocationName == Name))
4557 if((Ptr->EventTime > TDateTime(-1)) && (Ptr->LocationName == Name) && (Ptr->Command ==
"pas"))
4582 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition;
4600 CurrentTrackVectorPosition).
Attribute != 4))
4639 if((EntryPos == 0) || (EntryPos == 2))
4661 CurrentTrackVectorPosition = NextTrackVectorPosition;
4662 EntryPos = NextEntryPos;
4686 throw Exception(
"Error - failed to set ReturnVal in ClearToNextSignal()");
4712 bool PlatformFoundFlag =
false, StopRequired =
false, SkipRouteCheck =
false, RouteOrPartRouteSet =
false;
4713 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition, ElementNumber = 0, Distance = 0;
4714 int RouteStartPosition;
4716 int PlatformPosition;
4718 int EntryPos =
LeadEntryPos, ExitPos, NextEntryPos, RouteID;
4734 if(Distance > (4000 + LeadElementDistance))
4757 if(OtherTrain.
LeadElement == CurrentTrackVectorPosition)
4760 if((OtherCommand ==
"Fjo") || (OtherCommand ==
"jbo") || (OtherCommand ==
"cdt") || (OtherCommand ==
"Frh") ||
4806 if(!PlatformFoundFlag)
4808 PlatformPosition = CurrentTrackVectorPosition;
4811 PlatformFoundFlag =
true;
4827 if((EntryPos == 0) || (EntryPos == 2))
4871 if(ElementNumber < 2)
4873 SkipRouteCheck =
true;
4877 SkipRouteCheck =
false;
4879 if(ElementNumber == 1)
4881 RouteStartPosition = CurrentTrackVectorPosition;
4891 if(ElementNumber > 1)
4895 RouteOrPartRouteSet =
true;
4899 RouteOrPartRouteSet =
false;
4902 if(!SkipRouteCheck && !RouteOrPartRouteSet)
4909 int ExitLink = CurrentTrackElement.
Link[ExitPos];
4910 if((ExitLink == 1) || (ExitLink == 3) || (ExitLink == 7) || (ExitLink == 9))
4922 Distance += CurrentTrackElement.
Length01;
4926 Distance += CurrentTrackElement.
Length23;
4928 NextTrackVectorPosition = CurrentTrackElement.
Conn[ExitPos];
4929 NextEntryPos = CurrentTrackElement.
ConnLinkPos[ExitPos];
4930 CurrentTrackVectorPosition = NextTrackVectorPosition;
4931 EntryPos = NextEntryPos;
4968 return(RepeatHeadCode);
4990 bool FrontValid =
false, RearValid =
false;
4991 TTrackElement FrontAdjacentTrackElement, RearAdjacentTrackElement;
4995 TrainToBeJoinedBy = NULL;
5009 int TrainToBeJoinedByID = -1;
5030 if((TrainToBeJoinedByID < 0) && RearValid)
5049 if(TrainToBeJoinedByID < 0)
5051 TrainToBeJoinedBy = NULL;
5056 if(!TrainToBeJoinedBy->
Stopped())
5058 TrainToBeJoinedBy = NULL;
5069 TDateTime TimetableNonRepeatTime,
bool Warning)
5104 AnsiString(ActionType) +
"," + LocationName +
"," +
HeadCode);
5105 AnsiString BaseLog =
"", WarningBaseLog =
"", PerfLog =
"", ActionLog =
"";
5106 int IntMinsLate = 0;
5111 ActionLog =
" arrived at ";
5120 ActionLog =
" terminated at ";
5125 ActionLog =
" departed from ";
5127 if(ActionType ==
Pass)
5129 ActionLog =
" passed ";
5133 ActionLog =
" created at ";
5135 if(ActionType ==
Enter)
5137 ActionLog =
" entered railway at ";
5139 if(ActionType ==
Leave)
5141 ActionLog =
" left railway at ";
5145 ActionLog =
" split from front to ";
5149 ActionLog =
" split from rear to ";
5153 ActionLog =
" joined by ";
5157 ActionLog =
" changed direction at ";
5161 ActionLog =
" became new service ";
5165 ActionLog =
" taken under signaller control at ";
5169 ActionLog =
" restored to timetable control at ";
5175 ActionLog =
" REMOVED FROM RAILWAY DUE TO CRASH at ";
5179 ActionLog =
" REMOVED FROM RAILWAY DUE TO DERAILMENT at ";
5183 ActionLog =
" REMOVED FROM RAILWAY at ";
5188 ActionLog =
" received signaller authority to proceed";
5192 ActionLog =
" received signaller authority to step forward";
5196 ActionLog =
" changed direction under signaller control at ";
5200 ActionLog =
" received signaller authority to pass red signal";
5204 ActionLog =
" received signaller instruction to stop";
5208 ActionLog =
" stopped on signaller instruction ";
5212 ActionLog =
" joined under signaller control by ";
5216 ActionLog =
" suffered an onboard power failure at ";
5220 ActionLog =
" failure repaired at ";
5224 ActionLog =
" left railway under signaller control at ";
5226 if(OtherHeadCode !=
"")
5228 OtherHeadCode +=
" at ";
5235 WarningBaseLog =
HeadCode + ActionLog + OtherHeadCode + LocationName;
5241 bool TimePerformance =
true;
5249 TimePerformance =
false;
5253 double MinsLate = ((double)(ActualTime -
GetTrainTime(1, TimetableNonRepeatTime))) * 1440;
5255 if(ActionType ==
Pass)
5269 IntMinsLate = int(ceil(MinsLate));
5273 IntMinsLate = int(floor(MinsLate));
5275 if(IntMinsLate == 0)
5277 PerfLog =
" on time";
5279 else if(IntMinsLate == 1)
5281 PerfLog =
" 1 minute late";
5283 else if(IntMinsLate == -1)
5285 PerfLog =
" 1 minute early";
5287 else if(IntMinsLate > 1)
5289 PerfLog =
" " + AnsiString(IntMinsLate) +
" minutes late";
5291 else if(IntMinsLate < -1)
5293 int PosIntMinsLate = -IntMinsLate;
5294 PerfLog =
" " + AnsiString(PosIntMinsLate) +
" minutes early";
5296 if(LocationName.Pos(
'-') > 0)
5298 PerfLog =
"," + PerfLog;
5312 if((ActionType ==
Arrive) && (IntMinsLate == 0))
5316 else if((ActionType ==
Arrive) && (IntMinsLate > 0))
5321 else if((ActionType ==
Arrive) && (IntMinsLate < 0))
5327 else if((ActionType ==
Pass) && (IntMinsLate == 0))
5331 else if((ActionType ==
Pass) && (IntMinsLate > 0))
5336 else if((ActionType ==
Pass) && (IntMinsLate < 0))
5342 else if((ActionType ==
Leave) && (IntMinsLate == 0))
5346 else if((ActionType ==
Leave) && (IntMinsLate > 0))
5351 else if((ActionType ==
Leave) && (IntMinsLate < 0))
5357 else if((ActionType ==
Depart) && (IntMinsLate == 0))
5361 else if((ActionType ==
Depart) && (IntMinsLate > 0))
5380 AnsiString LocName =
"";
5447 if(LocationName ==
"")
5451 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
5452 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
5453 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
5457 if(LocationName !=
"")
5465 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5470 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5484 int LeadPosA = FirstNamedElementPos;
5485 int LeadPosB = FirstNamedLinkedElementPos;
5486 int LeadPosC = SecondNamedElementPos;
5487 int LeadPosD = SecondNamedLinkedElementPos;
5489 int LeadNumAtLoc = 0;
5506 if(LeadNumAtLoc < 4)
5510 SecondNamedLinkedElementPos))
5512 FirstNamedElementPos = LeadPosA;
5513 FirstNamedLinkedElementPos = LeadPosB;
5514 SecondNamedElementPos = LeadPosC;
5515 SecondNamedLinkedElementPos = LeadPosD;
5519 int MidNumAtLoc = 0;
5536 if(LeadNumAtLoc > MidNumAtLoc)
5539 FirstNamedElementPos = LeadPosA;
5540 FirstNamedLinkedElementPos = LeadPosB;
5541 SecondNamedElementPos = LeadPosC;
5542 SecondNamedLinkedElementPos = LeadPosD;
5556 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
5566 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5567 FrontTrainRearPosition = FirstNamedElementPos;
5568 RearTrainFrontPosition = SecondNamedElementPos;
5569 RearTrainRearPosition = SecondNamedLinkedElementPos;
5573 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5574 FrontTrainRearPosition = SecondNamedElementPos;
5575 RearTrainFrontPosition = FirstNamedElementPos;
5576 RearTrainRearPosition = FirstNamedLinkedElementPos;
5583 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5584 FrontTrainRearPosition = SecondNamedElementPos;
5585 RearTrainFrontPosition = FirstNamedElementPos;
5586 RearTrainRearPosition = FirstNamedLinkedElementPos;
5590 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5591 FrontTrainRearPosition = FirstNamedElementPos;
5592 RearTrainFrontPosition = SecondNamedElementPos;
5593 RearTrainRearPosition = SecondNamedLinkedElementPos;
5596 RearTrainExitPos = -1;
5597 for(
int x = 0; x < 4; x++)
5601 RearTrainExitPos = x;
5605 if(RearTrainExitPos == -1)
5607 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in FrontTrainSplit");
5609 FrontTrainExitPos = -1;
5610 for(
int x = 0; x < 4; x++)
5614 FrontTrainExitPos = x;
5618 if(FrontTrainExitPos == -1)
5620 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in FrontTrainSplit");
5623 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
5630 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
5650 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
5658 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
5659 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
5660 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
5757 if(LocationName ==
"")
5761 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
5762 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
5763 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
5767 if(LocationName !=
"")
5774 SecondNamedLinkedElementPos))
5778 SecondNamedLinkedElementPos))
5792 int LeadPosA = FirstNamedElementPos;
5793 int LeadPosB = FirstNamedLinkedElementPos;
5794 int LeadPosC = SecondNamedElementPos;
5795 int LeadPosD = SecondNamedLinkedElementPos;
5797 int LeadNumAtLoc = 0;
5814 if(LeadNumAtLoc < 4)
5818 SecondNamedLinkedElementPos))
5820 FirstNamedElementPos = LeadPosA;
5821 FirstNamedLinkedElementPos = LeadPosB;
5822 SecondNamedElementPos = LeadPosC;
5823 SecondNamedLinkedElementPos = LeadPosD;
5827 int MidNumAtLoc = 0;
5844 if(LeadNumAtLoc > MidNumAtLoc)
5847 FirstNamedElementPos = LeadPosA;
5848 FirstNamedLinkedElementPos = LeadPosB;
5849 SecondNamedElementPos = LeadPosC;
5850 SecondNamedLinkedElementPos = LeadPosD;
5864 throw Exception(
"Error - LocationName not set in RearTrainSplit");
5874 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5875 FrontTrainRearPosition = FirstNamedElementPos;
5876 RearTrainFrontPosition = SecondNamedElementPos;
5877 RearTrainRearPosition = SecondNamedLinkedElementPos;
5881 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5882 FrontTrainRearPosition = SecondNamedElementPos;
5883 RearTrainFrontPosition = FirstNamedElementPos;
5884 RearTrainRearPosition = FirstNamedLinkedElementPos;
5891 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5892 FrontTrainRearPosition = SecondNamedElementPos;
5893 RearTrainFrontPosition = FirstNamedElementPos;
5894 RearTrainRearPosition = FirstNamedLinkedElementPos;
5898 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5899 FrontTrainRearPosition = FirstNamedElementPos;
5900 RearTrainFrontPosition = SecondNamedElementPos;
5901 RearTrainRearPosition = SecondNamedLinkedElementPos;
5904 RearTrainExitPos = -1;
5905 for(
int x = 0; x < 4; x++)
5909 RearTrainExitPos = x;
5913 if(RearTrainExitPos == -1)
5915 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in RearTrainSplit");
5917 FrontTrainExitPos = -1;
5918 for(
int x = 0; x < 4; x++)
5922 FrontTrainExitPos = x;
5926 if(FrontTrainExitPos == -1)
5928 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in RearTrainSplit");
5931 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
5938 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
5958 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
5966 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
5967 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
5968 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
6107 TTrain *TrainToBeJoinedBy;
6140 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
6142 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass +
Mass);
6199 int RouteNumber = -1;
6207 bool FirstPass =
true;
6212 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6315 for(
int x = 0; x < IncNum; x++)
6348 else if(Ptr->
Command ==
"jbo")
6359 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6365 bool IncludeFER =
false;
6373 if(!IncludeFER && (Ptr->
Command ==
"Fer"))
6378 else if(IncludeFER && (Ptr->
Command ==
"Fer"))
6389 else if(Ptr->
Command ==
"Fjo")
6395 else if(Ptr->
Command ==
"Frh")
6405 else if(Ptr->
Command ==
"Frh-sh")
6456 else if(Ptr->
Command ==
"jbo")
6461 else if(Ptr->
Command ==
"cdt")
6469 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6841 int RouteNumber = -1;
6849 bool FirstPass =
true;
6854 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6882 ",FloatingLabelNextString" +
"," +
HeadCode);
6883 AnsiString RetStr =
"", LocationName =
"";
6887 throw Exception(
"Error - start entry in FloatingLabelNextString");
6927 else if(Ptr->
Command ==
"Fns")
6933 else if(Ptr->
Command ==
"F-nshs")
6964 RetStr =
"None, train terminated at " + Ptr->
LocationName;
6966 else if(Ptr->
Command ==
"Frh")
6968 RetStr =
"None, train terminated at " + Ptr->
LocationName;
6970 else if(Ptr->
Command ==
"Fer")
6972 AnsiString AllowedExits =
"";
6975 else if(Ptr->
Command ==
"Fjo")
6980 else if(Ptr->
Command ==
"jbo")
6985 else if(Ptr->
Command ==
"fsp")
6990 else if(Ptr->
Command ==
"rsp")
6995 else if(Ptr->
Command ==
"cdt")
7008 + AnsiString(RptNum) +
",CheckNewServiceDepartureTime," +
HeadCode);
7009 AnsiString DepTime =
"", EventTime =
"";
7010 bool CDTFlag =
false;
7014 if(AVI->Command ==
"cdt")
7019 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
7022 RetStr +=
"\nNew service splits at " + EventTime;
7026 if(AVI->Command ==
"jbo")
7029 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
7033 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
7038 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
7042 RetStr +=
"\nNew service departs at " + DepTime;
7058 ",FloatingTimetableString" +
"," +
HeadCode);
7059 AnsiString RetStr =
"", PartStr =
"";
7065 throw Exception(
"Error - start entry in FloatingTimetableString");
7068 bool FirstPass =
true;
7081 AnsiString TrainLoc =
"";
7119 AnsiString TrainLoc =
"";
7147 else if(Ptr->
Command ==
"Fns")
7153 else if(Ptr->
Command ==
"F-nshs")
7186 else if(Ptr->
Command ==
"Frh")
7190 else if(Ptr->
Command ==
"Fer")
7192 AnsiString AllowedExits =
"";
7195 else if(Ptr->
Command ==
"Fjo")
7200 else if(Ptr->
Command ==
"jbo")
7205 else if(Ptr->
Command ==
"fsp")
7210 else if(Ptr->
Command ==
"rsp")
7215 else if(Ptr->
Command ==
"cdt")
7221 RetStr = RetStr +
'\n' + PartStr;
7238 RetStr =
"Timetable finished";
7242 RetStr =
"No timetable";
7399 bool ForwardHeadCode;
7403 ForwardHeadCode =
true;
7408 ForwardHeadCode =
false;
7551 if(ColourNumber == 0)
7555 else if(ColourNumber == 1)
7559 else if(ColourNumber == 2)
7563 else if(ColourNumber == 3)
7567 else if(ColourNumber == 4)
7571 else if(ColourNumber == 5)
7575 else if(ColourNumber == 6)
7579 else if(ColourNumber == 7)
7583 else if(ColourNumber == 8)
7587 else if(ColourNumber == 9)
7591 else if(ColourNumber == 10)
7595 else if(ColourNumber == 11)
7599 else if(ColourNumber == 12)
7603 else if(ColourNumber == 13)
7607 else if(ColourNumber == 14)
7619 for(
int x = 0; x < 4; x++)
7626 for(
int x = 0; x < 4; x++)
7711 if((LocationAndMarker[1] !=
'*') && (LocationAndMarker.Length() > 6))
7714 AnsiString Location = LocationAndMarker.SubString(1, LocationAndMarker.Length() - 6);
7715 bool GiveMessagesFalse =
false;
7716 bool CheckLocationsExistInRailwayTrue =
true;
7723 AnsiString Marker = LocationAndMarker.SubString(LocationAndMarker.Length() - 5, 6);
7726 if(Marker[6] ==
'1')
8191 bool HideFlashingTrain =
true;
8194 Graphics::TBitmap *SmallTrainBitmap;
8235 HideFlashingTrain =
false;
8240 HideFlashingTrain =
false;
8245 HideFlashingTrain =
false;
8250 HideFlashingTrain =
false;
8255 HideFlashingTrain =
false;
8259 if((
LeadElement > -1) && (!HideFlashingTrain || Flash))
8263 if((
MidElement > -1) && (!HideFlashingTrain || Flash))
8287 for(
int y = 0; y < 3; y++)
8291 bool FoundFlag =
false;
8302 if(IMPair.first != IMPair.second)
8329 if((LocationName ==
"") && (
MidElement > -1))
8333 if((LocationName ==
"") && (
LagElement > -1))
8337 if(LocationName ==
"")
8339 throw Exception(
"Error - Location name not set in TrainAtLocation");
8350 for(
int x = 0; x < 4; x++)
8362 for(
int x = 0; x < 4; x++)
8379 AnsiString(LinkNumber) +
"," +
HeadCode);
8430 int DistanceToRedSignal = 0;
8431 float TimeToAct = 0;
8432 float MinsEarly = 0;
8433 TDateTime DepartureTime;
8434 TDateTime ArrivalTime;
8480 float CurrentStopTime;
8481 float LaterStopTime;
8482 float RecoverableTime;
8487 if(DistanceToRedSignal == -1)
8506 float TimeToSubtract, TotalStopTime;
8509 TimeToSubtract = RecoverableTime;
8553 if(CurrentStopTime > 0)
8555 TotalStopTime = CurrentStopTime + LaterStopTime;
8564 else if((MinsEarly > 0) && !
Stopped())
8566 TotalStopTime = LaterStopTime + MinsEarly;
8570 if(LaterStopTime == 0)
8572 TotalStopTime = CurrentStopTime;
8578 TotalStopTime = CurrentStopTime + LaterStopTime - TimeToSubtract;
8581 if(AvTrackSpeed < 30)
8585 int Speed = AvTrackSpeed;
8595 TimeToAct = TotalStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
8617 if((NextEntryPos == 0) || (NextEntryPos == 2))
8742 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8785 int IncrementalMinutes = 0;
8786 int IncrementalDigits = 0;
8794 throw Exception(
"Error - Repeat entry && less than two trains for Snt entry: " + TDEntry.
HeadCode);
8823 if(AVEntry0.
Command ==
"Snt-sh")
8828 int IncrementalMinutes = 0;
8829 int IncrementalDigits = 0;
8837 throw Exception(
"Error - Repeat entry && less than two trains for Snt-sh entry: " + TDEntry.
HeadCode);
8869 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8929 AnsiString Loc =
"";
8930 bool ElementFound =
false;
8935 ElementFound =
true;
8940 ElementFound =
true;
8945 ElementFound =
true;
8974 else if(AVEntryPtr->
Command ==
"Fer")
8976 bool CorrectExit =
false;
9084 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9099 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9114 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9125 bool TTrainController::AddTrain(
int Caller,
int RearPosition,
int FrontPosition, AnsiString HeadCode,
int StartSpeed,
int Mass,
double MaxRunningSpeed,
9126 double MaxBrakeRate,
double PowerAtRail, AnsiString ModeStr,
TTrainDataEntry *TrainDataEntryPtr,
int RepeatNumber,
int IncrementalMinutes,
9127 int IncrementalDigits,
int SignallerSpeed,
bool SignallerControl,
TActionEventType &EventType)
9129 LogEvent(AnsiString(Caller) +
",AddTrain," + AnsiString(RearPosition) +
"," + AnsiString(FrontPosition) +
"," + HeadCode +
"," + AnsiString(StartSpeed) +
9130 "," + AnsiString(Mass) +
"," + ModeStr);
9132 "," + HeadCode +
"," + AnsiString(StartSpeed) +
"," + AnsiString(Mass) +
"," + ModeStr +
"," + HeadCode);
9134 int RearExitPos = -1;
9136 for(
int x = 0; x < 4; x++)
9143 if(RearExitPos == -1)
9145 throw Exception(
"Error, RearExit == -1 in AddTrain");
9147 bool ReportFlag =
true;
9164 if(ModeStr ==
"Timetable")
9170 if(MaxRunningSpeed < 10)
9172 MaxRunningSpeed = 10;
9174 if(SignallerSpeed < 10)
9176 SignallerSpeed = 10;
9178 TTrain *NewTrain =
new TTrain(0, RearPosition, RearExitPos, HeadCode, StartSpeed, Mass, MaxRunningSpeed, MaxBrakeRate, PowerAtRail, TrainMode,
9179 TrainDataEntryPtr, RepeatNumber, IncrementalMinutes, IncrementalDigits, SignallerSpeed);
9184 if(SignallerControl)
9214 if(!SignallerControl)
9229 if(!SignallerControl)
9240 AnsiString Loc =
"";
9257 if(!SignallerControl)
9276 int RouteNumber = -1;
9277 bool SignalsSet =
false;
9284 int RouteStartPosition;
9288 if(FirstPair.first == RouteNumber)
9290 RouteStartPosition = FirstPair.second;
9292 else if(SecondPair.first == RouteNumber)
9294 RouteStartPosition = SecondPair.second;
9298 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 1st of 2 calls to SetAllRearwardsSignals in AddTrain");
9304 else if(RouteNumber > -1)
9324 int LinkedRouteNumber = -1;
9345 int RouteStartPosition;
9349 if(FirstPair.first == RouteNumber)
9351 RouteStartPosition = FirstPair.second;
9353 else if(SecondPair.first == RouteNumber)
9355 RouteStartPosition = SecondPair.second;
9359 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 2nd of 2 calls to SetAllRearwardsSignals in AddTrain");
9365 else if(RouteNumber > -1)
9385 int LinkedRouteNumber = -1;
9406 AnsiString(TrackVectorNumber));
9409 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9418 throw Exception(
"Error, VecPos not set in EntryPos");
9420 if(
TrainVectorAt(2, VecPos).LeadElement == TrackVectorNumber)
9425 else if(
TrainVectorAt(4, VecPos).MidElement == TrackVectorNumber)
9430 else if(
TrainVectorAt(6, VecPos).LagElement == TrackVectorNumber)
9444 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9452 throw Exception(
"Error - No Train identified in TrainVectorAtIdent with ID = " + AnsiString(TrainID));
9462 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9492 AnsiString RetStr =
"", PartStr =
"";
9500 if((Ptr->Command !=
"") && (Ptr->Command[1] ==
'S'))
9508 if(Ptr->SignallerControl)
9510 RetStr =
"Train under signaller control";
9515 if(Ptr->ArrivalTime == Ptr->DepartureTime)
9526 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime != TDateTime(-1)))
9530 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime == TDateTime(-1)))
9534 else if(Ptr->FormatType ==
PassTime)
9538 else if(Ptr->Command ==
"Fns")
9544 else if(Ptr->Command ==
"F-nshs")
9547 Ptr->NonRepeatingShuttleLinkHeadCode +
" at " + Ptr->LocationName;
9554 else if((Ptr->Command ==
"Fns-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
9561 else if((Ptr->Command ==
"Fns-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
9564 Ptr->NonRepeatingShuttleLinkHeadCode, +
" at " + Ptr->LocationName;
9567 else if((Ptr->Command ==
"Frh-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
9574 else if((Ptr->Command ==
"Frh-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
9576 PartStr =
"Terminate at " + Ptr->LocationName;
9578 else if(Ptr->Command ==
"Frh")
9580 PartStr =
"Terminate at " + Ptr->LocationName;
9582 else if(Ptr->Command ==
"Fer")
9584 AnsiString AllowedExits;
9588 else if(Ptr->Command ==
"Fjo")
9591 Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
9593 else if(Ptr->Command ==
"jbo")
9596 (50, Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
9598 else if(Ptr->Command ==
"fsp")
9603 else if(Ptr->Command ==
"rsp")
9608 else if(Ptr->Command ==
"cdt")
9614 RetStr = RetStr +
'\n' + PartStr;
9622 while(Ptr < TTDEPtr->ActionVector.end() && (Count < 33) && ((Ptr->Command ==
"") || ((Ptr->Command !=
"") && (Ptr->Command[1] !=
'F'))));
9635 + AnsiString(RptNum) +
",ControllerCheckNewServiceDepartureTime," + TDEPtr->
HeadCode);
9636 AnsiString DepTime =
"", EventTime =
"";
9637 bool CDTFlag =
false;
9641 if(AVI->Command ==
"cdt")
9646 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
9649 RetStr +=
"\nNew service splits at " + EventTime;
9653 if(AVI->Command ==
"jbo")
9656 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
9660 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
9665 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
9669 RetStr +=
"\nNew service departs at " + DepTime;
9829 ActiveTrackElementNameMapEntry.second = 0;
9835 std::ifstream TTBLFile(FileName, std::ios_base::binary);
9838 if(TTBLFile.is_open())
9840 char *TrainTimetableString =
new char[10000];
9842 bool EndOfFile =
false;
9845 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
9847 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
9854 delete[] TrainTimetableString;
9858 AnsiString OneLine(TrainTimetableString);
9859 bool FinalCallFalse =
false;
9860 while((Count == 0) && !
ProcessOneTimetableLine(5, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
9864 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
9865 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
9870 TimetableMessage(GiveMessages,
"Timetable invalid - unable to find a valid start time on its own line");
9872 delete[] TrainTimetableString;
9876 OneLine = AnsiString(TrainTimetableString);
9882 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
9884 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
9894 OneLine = AnsiString(TrainTimetableString);
9896 if(OneLine.Length() > 9999)
9898 TimetableMessage(GiveMessages,
"Timetable contains a line that is too long - 10,000 or more characters!");
9900 delete[] TrainTimetableString;
9904 bool FinalCallFalse =
false;
9905 if(!
ProcessOneTimetableLine(6, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
9909 delete[] TrainTimetableString;
9913 if(EndOfFile && (Count < 2))
9916 TimetableMessage(GiveMessages,
"Timetable has too few or no relevant entries - must have a start time on its own line and at least one train");
9918 delete[] TrainTimetableString;
9924 delete[] TrainTimetableString;
9929 TimetableMessage(GiveMessages,
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
9940 bool CheckLocationsExistInRailway)
10065 AnsiString((
short)FinalCall) +
"," + AnsiString((
short)CheckLocationsExistInRailway));
10075 if(OneLine[1] !=
'*')
10077 int SCPos = OneLine.Pos(
';');
10088 bool AllCommas =
true;
10090 for(
int x = 1; x < OneLine.Length() + 1; x++)
10092 if(OneLine[x] !=
',')
10097 if(AllCommas || (OneLine ==
""))
10112 AnsiString First =
"", Second =
"", Third =
"", Fourth =
"";
10113 int RearStartOrRepeatMins = 0, FrontStartOrRepeatDigits = 0, NumberOfRepeats = 0;
10114 TDateTime EventTime(0), ArrivalTime(0), DepartureTime(0);
10115 TDateTime StartTime(0);
10117 bool Warning =
false;
10144 AnsiString TrainInfoStr =
"", HeadCode =
"", Description =
"";
10145 int StartSpeed = 0, MaxRunningSpeed = 0, Mass = 0;
10146 double MaxBrakeRate = 0;
10147 double PowerAtRail = 0;
10148 int SignallerSpeed = 0;
10149 if(OneLine[1] ==
'*')
10155 int Pos = OneLine.Pos(
',');
10158 int SubStringLength = 20;
10159 if(OneLine.Length() < 20)
10161 SubStringLength = OneLine.Length();
10163 TimetableMessage(GiveMessages,
"Error in timetable - entry incomplete: see '" + OneLine.SubString(1, SubStringLength) +
"'....");
10167 TrainInfoStr = OneLine.SubString(1, Pos - 1);
10168 if(!
SplitTrainInfo(0, TrainInfoStr, HeadCode, Description, StartSpeed, MaxRunningSpeed, Mass, MaxBrakeRate, PowerAtRail, SignallerSpeed,
10178 TempTrainDataEntry.
HeadCode = HeadCode;
10182 TempTrainDataEntry.
Mass = Mass;
10190 AnsiString NewRemainder = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
10193 while(NewRemainder[NewRemainder.Length()] ==
',')
10195 if(NewRemainder.Length() > 1)
10197 NewRemainder = NewRemainder.SubString(1, NewRemainder.Length() - 1);
10206 if(NewRemainder ==
"")
10208 TimetableMessage(GiveMessages,
"Error in timetable - no events following train: '" + OneLine +
"'");
10213 int CommaCount = 0;
10214 for(
int x = 1; x < NewRemainder.Length() + 1; x++)
10216 if(NewRemainder[x] ==
',')
10221 if(CommaCount == 0)
10223 if((NewRemainder.SubString(7, 3) !=
"Snt") || (NewRemainder[NewRemainder.Length()] !=
'S'))
10225 int SubStringLength = 20;
10226 if(OneLine.Length() < 20)
10228 SubStringLength = OneLine.Length();
10231 "Error in timetable - must have at least a start and a finish event for a train that is not started under signaller control - see line beginning: '" +
10232 OneLine.SubString(1, SubStringLength) +
"'....");
10237 AnsiString OneEntry =
"";
10242 bool FinishFlag =
false;
10243 for(
int x = 0; x < CommaCount + 1; x++)
10245 if((CommaCount == 0) || (x < CommaCount))
10250 if(CommaCount == 0)
10252 OneEntry = NewRemainder;
10257 Pos = NewRemainder.Pos(
',');
10258 OneEntry = NewRemainder.SubString(1, Pos - 1);
10259 NewRemainder = NewRemainder.SubString(Pos + 1, NewRemainder.Length() - Pos);
10265 RearStartOrRepeatMins = 0;
10266 FrontStartOrRepeatDigits = 0;
10267 NumberOfRepeats = 0;
10268 if(!
SplitEntry(0, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
10269 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
10271 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
10276 if(Warning && (Second ==
"Frh"))
10278 TimetableMessage(GiveMessages,
"Error in line - '" + OneEntry +
"': warnings cannot be given for 'Frh' events");
10282 if(Warning && (Second ==
"Fjo"))
10285 "': warnings cannot be given for 'Fjo' events, for a train join warning add a 'W' prefix to the 'jbo' event");
10291 if(SequenceType !=
Start)
10293 TimetableMessage(GiveMessages,
"Error in timetable - First event not a start event: '" + OneEntry +
"'");
10297 if((Second ==
"Snt") && (Fourth ==
'S') && (NewRemainder !=
""))
10299 if(NewRemainder[1] !=
'R')
10302 "Error in timetable - the only event that can follow a train created under signaller control is a repeat, see '" +
10308 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
10312 if((HeadCode ==
"") || (Description ==
"") || (MaxRunningSpeed == 0) || (Mass == 0) || (MaxBrakeRate == 0))
10315 TimetableMessage(GiveMessages,
"Error in timetable - train information incomplete before 'Snt' or 'Snt-sh' start event: '" +
10321 if((Second ==
"Sfs") || (Second ==
"Sns") || (Second ==
"Sns-sh") || (Second ==
"Sns-fsh"))
10326 TimetableMessage(GiveMessages,
"Error in timetable - headcode missing before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
10331 if((StartSpeed != 0) || (MaxRunningSpeed != 0) || (Mass != 0) || (MaxBrakeRate != 0) || (PowerAtRail != 0))
10334 "Error in timetable - information additional to a headcode & optional description given before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
10341 if(SequenceType ==
Finish)
10350 TDateTime TempTime;
10356 ActionVectorEntry.
Warning = Warning;
10372 ActionVectorEntry.
Command = Second;
10387 else if(FormatType ==
TimeCmd)
10393 ActionVectorEntry.
Command = Second;
10401 ActionVectorEntry.
Command = Second;
10402 ActionVectorEntry.
ExitList = ExitList;
10410 ActionVectorEntry.
Command = Second;
10424 ActionVectorEntry.
Command = Second;
10435 ActionVectorEntry.
Command = Second;
10445 ActionVectorEntry.
Command = Second;
10454 ActionVectorEntry.
Command = Second;
10463 ActionVectorEntry.
Command = Second;
10469 ActionVectorEntry.
Command = Second;
10471 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
10476 OneEntry = NewRemainder;
10481 RearStartOrRepeatMins = 0;
10482 FrontStartOrRepeatDigits = 0;
10483 NumberOfRepeats = 0;
10484 if((FinishFlag) && (OneEntry[1] !=
'R'))
10487 TimetableMessage(GiveMessages,
"Error in timetable - Last event = '" + OneEntry +
"'. An earlier finish event has been found with something other than a repeat following it - only a repeat can follow a finish event.");
10491 if(OneEntry[1] !=
'R')
10493 if(!
SplitEntry(1, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
10494 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
10496 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
10500 if(SequenceType !=
Finish)
10502 TimetableMessage(GiveMessages,
"Error in timetable - last event should be a finish: '" + OneEntry +
"'");
10509 TDateTime TempTime;
10515 ActionVectorEntry.
Warning = Warning;
10522 ActionVectorEntry.
Command = Second;
10530 ActionVectorEntry.
Command = Second;
10539 ActionVectorEntry.
Command = Second;
10548 ActionVectorEntry.
Command = Second;
10558 ActionVectorEntry.
Command = Second;
10559 ActionVectorEntry.
ExitList = ExitList;
10563 ActionVectorEntry.
Command = Second;
10565 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
10570 if(!
SplitRepeat(0, OneEntry, RearStartOrRepeatMins, FrontStartOrRepeatDigits, NumberOfRepeats, GiveMessages))
10586 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
10605 if((HeadCode[HeadCode.Length() - 1] <
'0') || (HeadCode[HeadCode.Length() - 1] >
'9'))
10610 if((HeadCode[HeadCode.Length()] <
'0') || (HeadCode[HeadCode.Length()] >
'9'))
10625 if(TimeStr.Length() < 5)
10630 if((TimeStr[1] <
'0') || (TimeStr[1] >
'9'))
10635 if((TimeStr[2] <
'0') || (TimeStr[2] >
'9'))
10640 if(TimeStr[3] !=
':')
10645 if((TimeStr[4] <
'0') || (TimeStr[4] >
'5'))
10650 if((TimeStr[5] <
'0') || (TimeStr[5] >
'9'))
10655 while(TimeStr.Length() > 5)
10657 TimeStr = TimeStr.SubString(1, TimeStr.Length() - 1);
10659 double WholeHours = (AnsiString(TimeStr[1]) + AnsiString(TimeStr[2])).ToDouble();
10660 double FracHour = ((AnsiString(TimeStr[4]) + AnsiString(TimeStr[5])).ToDouble()) / 60.0;
10662 if((WholeHours + FracHour) >= 95.98334)
10667 Time = TDateTime((WholeHours + FracHour) / 24);
10674 bool TTrainController::SplitEntry(
int Caller, AnsiString OneEntry,
bool GiveMessages,
bool CheckLocationsExistInRailway, AnsiString &First, AnsiString &Second,
10675 AnsiString &Third, AnsiString &Fourth,
int &RearStartOrRepeatMins,
int &FrontStartOrRepeatDigits,
TTimetableFormatType &FormatType,
10684 TDateTime TempTime;
10686 if(OneEntry.Length() > 0)
10688 if(OneEntry[1] ==
'W')
10691 OneEntry = OneEntry.SubString(2, OneEntry.Length() - 1);
10695 if(OneEntry ==
"Frh")
10705 if(OneEntry.Length() < 7)
10710 int Pos = OneEntry.Pos(
';');
10718 First = OneEntry.SubString(1, 5);
10724 AnsiString Remainder = OneEntry.SubString(Pos + 1, OneEntry.Length() - Pos);
10726 if((Remainder[1] >=
'0') && (Remainder[1] <=
'9'))
10729 if(Remainder.Length() < 7)
10734 Pos = Remainder.Pos(
';');
10741 Second = Remainder.SubString(1, 5);
10747 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10760 Pos = Remainder.Pos(
';');
10763 Second = Remainder;
10764 if(Second ==
"cdt")
10789 if((Pos != 4) && (Pos != 7) && (Pos != 8))
10795 Second = Remainder.SubString(1, Pos - 1);
10797 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10799 Pos = Remainder.Pos(
';');
10806 Third = Remainder.SubString(1, Pos - 1);
10807 Fourth = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10809 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
10812 int SpacePos = Third.Pos(
' ');
10818 AnsiString RearStartStr = Third.SubString(1, SpacePos - 1);
10819 AnsiString FrontStartStr = Third.SubString(SpacePos + 1, Third.Length() - SpacePos);
10821 if(CheckLocationsExistInRailway)
10831 if(Second ==
"Snt")
10834 SequenceType =
Start;
10843 SequenceType =
Start;
10854 if(Second ==
"Sns-sh")
10858 SequenceType =
Start;
10873 if(Second ==
"F-nshs")
10887 if(Second ==
"Sns-fsh")
10891 SequenceType =
Start;
10901 if(Second ==
"Fns-sh")
10921 if(Second ==
"pas")
10936 if(Second ==
"Fer")
10943 if(CheckLocationsExistInRailway)
10955 if((Second !=
"Fns") && (Second !=
"Fjo") && (Second !=
"jbo") && (Second !=
"fsp") && (Second !=
"rsp") && (Second !=
"Sfs") && (Second !=
"Sns") &&
10956 (Second !=
"Frh-sh"))
10968 if(Second ==
"Frh-sh")
10976 if((Second ==
"Fns") || (Second ==
"Fjo") || (Second ==
"Frh-sh"))
10980 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
10984 if((Second ==
"Sfs") || (Second ==
"Sns"))
10986 SequenceType =
Start;
11004 if((LocStr[1] >=
'0') && (LocStr[1] <=
'9'))
11009 for(
int x = 1; x < LocStr.Length() + 1; x++)
11011 if(LocStr[x] <
' ')
11016 if(LocStr[x] >
'z')
11023 if(CheckLocationsExistInRailway)
11028 "' appears in the timetable but is not a valid name. To be valid the name must be a stopping location and apply to one or more platforms " +
11029 "(not concourses on their own), or to track at a blue non-station named location. BUT NOTE THAT trains can't stop at continuations so a name " +
11030 "that includes a continuation will not be valid.");
11048 if((HeadCode.Length() < 4) || (HeadCode.Length() > 8))
11051 "', length must be between 4 and 8 characters, and last 4 must be a legitimate headcode. This error can also be caused by omitting a service reference after Sns, Snt-sh, Sns-sh, Fns, Fns-sh or Frh-sh");
11056 for(
int x = 1; x < (HeadCode.Length() + 1); x++)
11058 if((HeadCode[x] <
' ') || (HeadCode[x] >
'~'))
11060 TimetableMessage(GiveMessages,
"Non-printable character in headcode '" + HeadCode +
"'");
11066 for(
int x = 3; x >= 0; x--)
11068 if(((HeadCode[HeadCode.Length() - x] <
'A') || (HeadCode[HeadCode.Length() - x] >
'Z')) && ((HeadCode[HeadCode.Length() - x] <
'a') ||
11069 (HeadCode[HeadCode.Length() - x] >
'z')) && ((HeadCode[HeadCode.Length() - x] <
'0') || (HeadCode[HeadCode.Length() - x] >
'9')))
11071 TimetableMessage(GiveMessages,
"Headcode error in '" + HeadCode +
"', headcode must consist of letters and digits only");
11087 AnsiString CurrentID =
"";
11089 if(IDSet.Length() == 0)
11091 TimetableMessage(GiveMessages,
"Must have at least one exit element ID following 'Fer'");
11095 for(
int x = 1; x <= IDSet.Length(); x++)
11098 if(((C <
'0') || (C >
'9')) && (C !=
' ') && (C !=
'N') && (C !=
'-'))
11100 TimetableMessage(GiveMessages,
"Illegal character in the set of element IDs following 'Fer' in '" + IDSet +
"'");
11105 int Pos = IDSet.Pos(
' ');
11116 CurrentID = IDSet.SubString(1, Pos - 1);
11117 IDSet = IDSet.SubString(Pos + 1, IDSet.Length() - Pos);
11129 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' is not an exit");
11136 if(!ExitList.empty())
11138 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
11140 if(*ELIT == VecPos)
11142 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' duplicates an earlier element");
11149 ExitList.push_back(VecPos);
11159 Pos = IDSet.Pos(
' ');
11166 int &Mass,
double &MaxBrakeRate,
double &PowerAtRail,
int &SignallerSpeed,
bool GiveMessages)
11173 AnsiString Remainder =
"";
11174 int SemiColonCount = 0;
11176 for(
int x = 1; x < TrainInfoStr.Length() + 1; x++)
11178 if(TrainInfoStr[x] ==
';')
11183 if((SemiColonCount != 6) && (SemiColonCount != 7) && (SemiColonCount != 1) && (SemiColonCount != 0))
11185 TimetableMessage(GiveMessages,
"Error in train information in '" + TrainInfoStr +
11186 "'. Should be headcode + optional description for a continuing service;" +
11187 " or headcode, description, start speed, max running speed, mass, brake force, power (and optional signaller max. speed) for a new service");
11191 if(SemiColonCount == 0)
11193 HeadCode = TrainInfoStr;
11202 if(SemiColonCount == 1)
11204 Pos = TrainInfoStr.Pos(
';');
11205 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
11206 Description = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
11212 if(Description ==
"")
11214 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
11218 if(Description.Length() > 60)
11220 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
11224 for(
int x = 1; x < Description.Length() + 1; x++)
11226 if((Description[x] <
' ') || (Description[x] >
'~'))
11228 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
11237 Pos = TrainInfoStr.Pos(
';');
11238 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
11239 Remainder = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
11245 Pos = Remainder.Pos(
';');
11246 Description = Remainder.SubString(1, Pos - 1);
11247 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11248 if(Description ==
"")
11250 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
11254 if(Description.Length() > 60)
11256 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
11260 for(
int x = 1; x < Description.Length() + 1; x++)
11262 if((Description[x] <
' ') || (Description[x] > 126))
11264 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
11269 Pos = Remainder.Pos(
';');
11270 AnsiString StartSpeedStr = Remainder.SubString(1, Pos - 1);
11272 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11273 if(StartSpeedStr ==
"")
11275 TimetableMessage(GiveMessages,
"Train starting speed missing in '" + TrainInfoStr +
"'");
11279 for(
int x = 1; x < StartSpeedStr.Length() + 1; x++)
11281 if((StartSpeedStr[x] <
'0') || (StartSpeedStr[x] >
'9'))
11283 TimetableMessage(GiveMessages,
"Train start speed contains invalid characters in '" + TrainInfoStr +
"'");
11288 StartSpeed = StartSpeedStr.ToInt();
11294 TimetableMessage(GiveMessages,
"Train starting speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
11298 Pos = Remainder.Pos(
';');
11299 AnsiString MaxRunningSpeedStr = Remainder.SubString(1, Pos - 1);
11301 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11302 if(MaxRunningSpeedStr ==
"")
11304 TimetableMessage(GiveMessages,
"Train maximum running speed missing in '" + TrainInfoStr +
"'");
11308 for(
int x = 1; x < MaxRunningSpeedStr.Length() + 1; x++)
11310 if((MaxRunningSpeedStr[x] <
'0') || (MaxRunningSpeedStr[x] >
'9'))
11312 TimetableMessage(GiveMessages,
"Train maximum running speed contains invalid characters in '" + TrainInfoStr +
"'");
11317 MaxRunningSpeed = MaxRunningSpeedStr.ToInt();
11323 TimetableMessage(GiveMessages,
"Train maximum running speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
11327 if(MaxRunningSpeed < 10)
11330 MaxRunningSpeed = 10;
11333 TimetableMessage(GiveMessages,
"Train maximum running speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
11337 Pos = Remainder.Pos(
';');
11338 AnsiString MassStr = Remainder.SubString(1, Pos - 1);
11340 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11343 TimetableMessage(GiveMessages,
"Train mass missing in '" + TrainInfoStr +
"'");
11347 for(
int x = 1; x < MassStr.Length() + 1; x++)
11349 if((MassStr[x] <
'0') || (MassStr[x] >
'9'))
11351 TimetableMessage(GiveMessages,
"Train mass contains invalid characters in '" + TrainInfoStr +
"'");
11356 Mass = MassStr.ToInt() * 1000;
11362 TimetableMessage(GiveMessages,
"Train mass > 10,000 tonnes in '" + TrainInfoStr +
"'. Setting it to 10,000 tonnes");
11368 TimetableMessage(GiveMessages,
"Train mass zero in '" + TrainInfoStr +
"'");
11372 Pos = Remainder.Pos(
';');
11373 AnsiString MaxBrakeForceStr = Remainder.SubString(1, Pos - 1);
11375 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11376 if(MaxBrakeForceStr ==
"")
11378 TimetableMessage(GiveMessages,
"Train braking force missing in '" + TrainInfoStr +
"'");
11382 for(
int x = 1; x < (MaxBrakeForceStr.Length() + 1); x++)
11384 if((MaxBrakeForceStr[x] !=
'.') && ((MaxBrakeForceStr[x] <
'0') || (MaxBrakeForceStr[x] >
'9')))
11386 TimetableMessage(GiveMessages,
"Train braking force contains invalid characters in '" + TrainInfoStr +
"'");
11391 double MaxBrakeForce = MaxBrakeForceStr.ToDouble() * 1000;
11394 if((MaxBrakeForce / Mass) > 1)
11396 MaxBrakeForce = Mass;
11399 TimetableMessage(GiveMessages,
"Train braking force too high in '" + TrainInfoStr +
"'. Setting it to the same as the train mass");
11403 if((MaxBrakeForce / Mass) < 0.01)
11405 MaxBrakeForce = Mass * 0.01;
11408 TimetableMessage(GiveMessages,
"Train braking force too low in '" + TrainInfoStr +
"'. Setting it to 1% of the train mass");
11413 MaxBrakeRate = MaxBrakeForce / Mass * 9.81;
11415 AnsiString GrossPowerStr =
"", SignallerSpeedStr =
"";
11417 if(SemiColonCount == 6)
11419 GrossPowerStr = Remainder;
11420 SignallerSpeedStr =
"30";
11424 Pos = Remainder.Pos(
';');
11425 GrossPowerStr = Remainder.SubString(1, Pos - 1);
11426 SignallerSpeedStr = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11429 if(GrossPowerStr ==
"")
11431 TimetableMessage(GiveMessages,
"Train power missing in '" + TrainInfoStr +
"'");
11435 for(
int x = 1; x < GrossPowerStr.Length() + 1; x++)
11437 if((GrossPowerStr[x] <
'0') || (GrossPowerStr[x] >
'9'))
11439 TimetableMessage(GiveMessages,
"Train power contains invalid characters in '" + TrainInfoStr +
"'");
11445 double GrossPower = GrossPowerStr.ToInt() * 1000;
11452 TimetableMessage(GiveMessages,
"Train power > 100,000kW in '" + TrainInfoStr +
"'. Setting it to 100,000kW");
11456 else if(GrossPower == 0)
11461 else if((GrossPower > 0) && (GrossPower < 10000))
11464 GrossPower = 10000;
11466 PowerAtRail = GrossPower * 0.8;
11470 if(SignallerSpeedStr ==
"")
11472 TimetableMessage(GiveMessages,
"Signaller speed not set in '" + TrainInfoStr +
"', either set a value or remove the extra semicolon");
11476 for(
int x = 1; x < SignallerSpeedStr.Length() + 1; x++)
11478 if((SignallerSpeedStr[x] <
'0') || (SignallerSpeedStr[x] >
'9'))
11480 TimetableMessage(GiveMessages,
"Signaller speed contains invalid characters in '" + TrainInfoStr +
"'");
11485 SignallerSpeed = SignallerSpeedStr.ToInt();
11491 TimetableMessage(GiveMessages,
"Signaller speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
11495 if(SignallerSpeed < 10)
11498 SignallerSpeed = 10;
11501 TimetableMessage(GiveMessages,
"Signaller speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
11519 if(OneEntry.Length() < 7)
11521 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
11525 int SemiColonCount = 0;
11527 for(
int x = 1; x < OneEntry.Length() + 1; x++)
11529 if(OneEntry[x] ==
';')
11534 if(SemiColonCount != 3)
11536 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
11540 if((OneEntry[1] !=
'R') || (OneEntry[2] !=
';'))
11542 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
11546 AnsiString Remainder = OneEntry.SubString(3, OneEntry.Length() - 2);
11551 Pos = Remainder.Pos(
';');
11552 AnsiString MinutesStr = Remainder.SubString(1, Pos - 1);
11554 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11555 if(MinutesStr ==
"")
11557 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute increment segment missing");
11561 if(MinutesStr.Length() > 3)
11564 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute value too high, maximum value is 999");
11568 for(
int x = 1; x < MinutesStr.Length() + 1; x++)
11570 if((MinutesStr[x] <
'0') || (MinutesStr[x] >
'9'))
11572 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in minute increment segment");
11577 RearStartOrRepeatMins = MinutesStr.ToInt();
11578 if(RearStartOrRepeatMins == 0)
11580 TimetableMessage(GiveMessages,
"Repeat minute increment is zero in: '" + OneEntry +
"' - can't have a zero value");
11584 Pos = Remainder.Pos(
';');
11585 AnsiString DigitsStr = Remainder.SubString(1, Pos - 1);
11587 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11588 if(DigitsStr ==
"")
11590 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - headcode increment segment missing");
11594 for(
int x = 1; x < DigitsStr.Length() + 1; x++)
11596 if((DigitsStr[x] <
'0') || (DigitsStr[x] >
'9'))
11598 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in headcode increment segment");
11603 if(DigitsStr.Length() > 2)
11605 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - maximum number of digits for headcode increment is 2");
11609 FrontStartOrRepeatDigits = DigitsStr.ToInt();
11623 "' - a repeating service with incrementing digits must have digits as its last two headcode characters");
11627 AnsiString NumberStr = Remainder;
11629 if(NumberStr ==
"")
11631 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - number of repeats missing");
11635 if(NumberStr.Length() > 4)
11638 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - repeat value too high, no timetabled event can exceed 95 hours & 59 minutes");
11642 for(
int x = 1; x < NumberStr.Length() + 1; x++)
11644 if((NumberStr[x] <
'0') || (NumberStr[x] >
'9'))
11647 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in number of repeats");
11652 NumberOfRepeats = NumberStr.ToInt();
11653 if(NumberOfRepeats == 0)
11655 TimetableMessage(GiveMessages,
"Number of repeats is zero in: '" + OneEntry +
"' - if no repeats are needed the repeat should be omitted");
11827 SecondPassMessage(GiveMessages,
"Error in timetable - there appear to be no train services in the timetable, it must contain at least one");
11846 TwoLocationFlag =
false;
11852 SecondPassMessage(GiveMessages,
"Error in timetable - the following service has no listed events, there must be at least one: " + TDEntry.
HeadCode);
11866 SecondPassMessage(GiveMessages,
"Error in timetable - service must have a start event and at least one other for: " + TDEntry.
HeadCode);
11882 "Error in timetable - a signaller control service can have no more than one item (a repeat) after the start event, see: " +
11894 "Error in timetable - a signaller control service cannot have any other than a repeat after the start event, see: " + TDEntry.
HeadCode);
11921 SecondPassMessage(GiveMessages,
"Error in timetable - finish events Fns-sh and Frh-sh not permitted immediately after an Snt entry for: " +
11932 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11937 SecondPassMessage(GiveMessages,
"Error in timetable - a start event is present that is not the first event for: " + TDEntry.
HeadCode);
11947 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11952 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat is present that is not the last item for: " + TDEntry.
HeadCode);
11962 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11973 SecondPassMessage(GiveMessages,
"Error in timetable - the last item must be either a finish event or a repeat for: " + TDEntry.
HeadCode);
11983 SecondPassMessage(GiveMessages,
"Error in timetable - the last event before the repeat must be a finish for: " + TDEntry.
HeadCode);
11995 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12002 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event must be either the last or last but one for: " + TDEntry.
HeadCode);
12011 SecondPassMessage(GiveMessages,
"Error in timetable - the only event that can follow a finish event is a repeat for: " +
12031 if((AVEntry0.
Command ==
"Snt") || (AVEntry0.
Command ==
"Snt-sh"))
12033 AnsiString LocationName =
"";
12049 SecondPassMessage(GiveMessages,
"Error in timetable - stopped 'Snt' or 'Snt-sh' followed by an illegal event for: " +
12050 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
12059 SecondPassMessage(GiveMessages,
"Error in timetable - 'Snt' or 'Snt-sh' event at stop location but start speed not zero for: " +
12068 if(AVEntry0.
Command ==
"Snt-sh")
12082 SecondPassMessage(GiveMessages,
"Error in timetable - unlocated 'Snt' not followed by 'Fer', 'pas' or an arrival for: " +
12098 SecondPassMessage(GiveMessages,
"Error in timetable - 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' followed by an illegal event for: " +
12099 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
12110 bool FoundFlag =
false;
12116 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12128 SecondPassMessage(GiveMessages,
"Error in timetable - no location departure following an 'Sfs', 'Sns', 'Sns-sh'or 'Sns-fsh' event for: " +
12141 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12150 ": an event should have had a location name associated with it but it could not be found");
12156 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
12178 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12188 SecondPassMessage(GiveMessages,
"Error in timetable - only a repeat can follow a finish entry for: " + TDEntry.
HeadCode);
12195 if(AVEntry.
Command ==
"F-nshs")
12200 SecondPassMessage(GiveMessages,
"Error in timetable - F-nshs (shuttle link) must be the last event for: " + TDEntry.
HeadCode);
12228 SecondPassMessage(GiveMessages,
"Error in timetable - a jbo event is followed by an illegal event for: " + TDEntry.
HeadCode +
12229 ". The event isn't valid for a stationary train.");
12239 SecondPassMessage(GiveMessages,
"Error in timetable - a train split can't be the last event for: " + TDEntry.
HeadCode);
12247 SecondPassMessage(GiveMessages,
"Error in timetable - a train split is followed by an illegal event for: " + TDEntry.
HeadCode +
12248 ". The event isn't valid for a stationary train.");
12266 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cdt' is followed by an illegal event for: " + TDEntry.
HeadCode +
12267 ". The event isn't valid for a stationary train.");
12277 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure can't be the last event for: " + TDEntry.
HeadCode);
12285 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure is followed by an illegal event for: " +
12286 TDEntry.
HeadCode +
". The event isn't valid for a moving train.");
12304 SecondPassMessage(GiveMessages,
"Error in timetable - a pass time is followed by an illegal event for: " + TDEntry.
HeadCode +
12305 ". The event isn't valid for a moving train.");
12327 bool LastEntryIsAnArrival =
false;
12334 LastEntryIsAnArrival =
false;
12335 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12342 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
12344 if(LastEntryIsAnArrival)
12348 LastEntryIsAnArrival =
false;
12354 LastEntryIsAnArrival =
true;
12361 LastEntryIsAnArrival =
true;
12362 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12369 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
12371 if(LastEntryIsAnArrival)
12375 LastEntryIsAnArrival =
false;
12381 LastEntryIsAnArrival =
true;
12391 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12399 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival can't be the last event for: " + TDEntry.
HeadCode);
12407 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival is followed by an illegal event for: " + TDEntry.
HeadCode +
12408 ". The event isn't valid for a stationary train.");
12419 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure can't be the last event for: " + TDEntry.
HeadCode);
12427 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure is followed by an illegal event for: " + TDEntry.
HeadCode +
12428 ". The event isn't valid for a moving train.");
12442 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12449 throw Exception(
"Timetable error, TimeLoc entry has EventTime not -1 for " + TDEntry.
HeadCode);
12453 throw Exception(
"Timetable error, TimeLoc entry has neither arrival nor departure time set for " + TDEntry.
HeadCode);
12460 throw Exception(
"Timetable error, TimeTimeLoc entry has EventTime not -1 for " + TDEntry.
HeadCode);
12464 throw Exception(
"Timetable error, TimeTimeLoc entry has either arrival or departure time not set for " + TDEntry.
HeadCode);
12473 throw Exception(
"Timetable error, Cmd or PassTime entry has EventTime not set for " + TDEntry.
HeadCode);
12477 throw Exception(
"Timetable error, Cmd or PassTime entry has either arrival or departure time set for " + TDEntry.
HeadCode);
12484 throw Exception(
"Timetable error, Repeat entry has a time set for " + TDEntry.
HeadCode);
12495 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12510 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has a later arrival than departure time for: " +
12518 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has too early an arrival time for: " +
12533 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
12545 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
12557 SecondPassMessage(GiveMessages,
"Error in timetable - a train event has a time that is set too early for: " + TDEntry.
HeadCode +
12558 ", may be before timetable start time");
12569 AnsiString LastLocationName =
"";
12573 bool LastEntryIsAnArrival =
false;
12578 LastEntryIsAnArrival =
false;
12579 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
12580 if(LastLocationName !=
"")
12582 throw Exception(
"Timetable error, moving Snt entry has LocationName set for " + TDEntry.
HeadCode);
12584 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size();
12597 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
12609 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
12622 TwoLocationFlag =
true;
12627 LastEntryIsAnArrival =
false;
12631 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
12634 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
12639 else if(!LastEntryIsAnArrival && (AVEntry.
LocationName == LastLocationName))
12642 "Error in timetable - a location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode);
12648 LastEntryIsAnArrival = !LastEntryIsAnArrival;
12654 LastEntryIsAnArrival =
true;
12655 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
12656 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12668 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
12680 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
12693 TwoLocationFlag =
true;
12698 LastEntryIsAnArrival =
false;
12702 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
12705 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
12713 "A location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode +
". Please correct if this is an error.\n\nThis warning will not be shown again.");
12720 LastEntryIsAnArrival = !LastEntryIsAnArrival;
12728 AnsiString LocationNameToBeChecked =
"";
12733 unsigned int y = 0;
12747 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
12748 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
12766 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
12775 TwoLocationFlag =
true;
12786 if(TwoLocationFlag)
12796 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12801 throw Exception(
"Error, non- 'Snt', 'Fer' or Repeat entry doesn't have a location name set for " + TDEntry.
HeadCode);
12803 AnsiString LocName =
"";
12809 throw Exception(
"Error, 'Snt' entry at a stop location doesn't have a location name set for " + TDEntry.
HeadCode);
12816 throw Exception(
"Error, 'Snt' unlocated entry has a location name set for " + TDEntry.
HeadCode);
12839 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12864 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12886 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12908 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12927 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12930 if((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh"))
12945 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12950 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has FormatType unset for: " + TDEntry.
HeadCode);
12954 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has SequenceType unset for: " + TDEntry.
HeadCode);
12958 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has LocationType unset for: " + TDEntry.
HeadCode);
12962 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has ShuttleLinkType unset for: " + TDEntry.
HeadCode);
13001 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13003 AnsiString LocName =
TrainDataVector.at(x).ActionVector.at(y).LocationName;
13009 SecondPassMessage(GiveMessages,
"Error in timetable - continuation names (" + LocName +
") must not be included, see service " + HC);
13022 int IncMinutes = 0;
13032 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13038 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat time exceeds 95h 59m, see service " + HC);
13044 if((
double)
TrainDataVector.at(x).ActionVector.at(y).ArrivalTime > -1)
13049 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat entry time exceeds 95h 59m, see service " + HC);
13055 if((
double)
TrainDataVector.at(x).ActionVector.at(y).DepartureTime > -1)
13060 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat entry time exceeds 95h 59m, see service " + HC);
13073 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13099 (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"F-nshs"));
13107 if(HeadCode.Length() > 4)
13109 HeadCode = HeadCode.SubString(HeadCode.Length() - 3, 4);
13120 int ForwardCount = 0;
13121 int ReverseCount = 0;
13123 if(MainHeadCode == SecondHeadCode)
13125 SecondPassMessage(GiveMessages,
"Error in timetable - Service " + MainHeadCode +
" has an event that references itself");
13134 if(TDEntry.
HeadCode == MainHeadCode)
13136 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13151 if(ForwardCount == 0)
13154 throw Exception(
"Error, ForwardCount == 0 in CheckForDuplicateCrossReferences after called with found values");
13156 if(ForwardCount > 2)
13159 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + SecondHeadCode +
" from a train whose headcode is " +
13160 MainHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
13169 if(TDEntry.
HeadCode == SecondHeadCode)
13171 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13186 if(ReverseCount == 0)
13188 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + SecondHeadCode);
13193 if(ReverseCount > 2)
13196 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + MainHeadCode +
" from a train whose headcode is " +
13197 SecondHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
13202 if(ForwardCount != ReverseCount)
13204 SecondPassMessage(GiveMessages,
"Error in timetable - " + MainHeadCode +
" has a different number of references to " + SecondHeadCode +
13205 " than the other way round");
13236 int ForwardCount = 0;
13237 int ReverseCount = 0;
13238 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
13247 if(TDEntry.
HeadCode == MainHeadCode)
13249 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13252 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
13257 ForwardEntryPtr = &AVEntry;
13259 ForwardTDVectorNumber = x;
13262 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") ||
13263 (AVEntry.
Command ==
"Frh-sh")))
13268 ForwardEntryPtr = &AVEntry;
13270 ForwardTDVectorNumber = x;
13276 if(ForwardCount == 0)
13279 throw Exception(
"Error, ForwardCount == 0 in CheckCrossReferencesAndSetData after called with found values");
13281 if(ForwardCount > 1)
13283 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + OtherHeadCode +
" from a train whose headcode is " +
13293 if(TDEntry.
HeadCode == OtherHeadCode)
13295 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13298 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
13304 ReverseEntryPtr = &AVEntry;
13305 ReverseTDVectorNumber = x;
13308 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"Frh-sh")))
13314 ReverseEntryPtr = &AVEntry;
13315 ReverseTDVectorNumber = x;
13322 if(ReverseCount == 0)
13324 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + OtherHeadCode);
13329 if(ReverseCount > 1)
13331 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
13338 bool ForwardShuttleStart = ((ForwardEntryPtr->Command ==
"Sns-sh") || (ForwardEntryPtr->Command ==
"Snt-sh"));
13339 bool ForwardShuttleFinish = ((ForwardEntryPtr->Command ==
"Fns-sh") || (ForwardEntryPtr->Command ==
"Frh-sh"));
13340 bool ReverseShuttleStart = ((ReverseEntryPtr->
Command ==
"Sns-sh") || (ReverseEntryPtr->
Command ==
"Snt-sh"));
13341 bool ReverseShuttleFinish = ((ReverseEntryPtr->
Command ==
"Fns-sh") || (ReverseEntryPtr->
Command ==
"Frh-sh"));
13345 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat");
13352 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + OtherHeadCode +
" does not have a repeat");
13357 if(ForwardEntryPtr->LocationName ==
"")
13359 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
13360 ". One or other service does not have a location set");
13367 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
13368 ". One or other service does not have a location set");
13373 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
13375 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
13376 " is at a different location to the referencing train " + MainHeadCode);
13384 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
13386 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
13387 " has a different event time to the referencing train " + MainHeadCode);
13395 if(ForwardShuttleStart && ReverseShuttleFinish)
13400 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle service " + MainHeadCode +
13401 " first repeat restart time not consistent with finish service " + OtherHeadCode);
13407 if((ReverseEntryPtr->
Command ==
"Sfs") || (ReverseEntryPtr->
Command ==
"Sns"))
13410 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
13412 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' or 'Sns' event (" + OtherHeadCode +
13413 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
13419 if(ReverseEntryPtr->
Command ==
"Fjo")
13422 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
13424 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fjo' event (" + OtherHeadCode +
13425 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
13431 if(ReverseEntryPtr->
Command ==
"Fns")
13434 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
13436 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' event (" + OtherHeadCode +
13437 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
13443 if(ForwardEntryPtr->Command ==
"Sfs")
13445 if((ReverseEntryPtr->
Command !=
"fsp") && (ReverseEntryPtr->
Command !=
"rsp"))
13448 "Error in timetable - unable to find a corresponding split train event for the train that starts from a split whose headcode is " +
13455 if((ForwardEntryPtr->Command ==
"fsp") || (ForwardEntryPtr->Command ==
"rsp"))
13457 if(ReverseEntryPtr->
Command !=
"Sfs")
13459 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sfs' event for the train split whose headcode is " +
13469 SecondPassMessage(GiveMessages,
"Error in timetable - can't find timetabled location '" + ForwardEntryPtr->LocationName +
"' in railway - perhaps there are concourses without platforms?");
13476 SecondPassMessage(GiveMessages,
"Error in timetable - can't find any named location elements at '" + ForwardEntryPtr->LocationName +
"' - perhaps there are concourses without platforms?");
13483 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
13488 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
13499 if(ForwardEntryPtr->Command ==
"Sns")
13501 if(ReverseEntryPtr->
Command !=
"Fns")
13503 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fns' event for the 'Sns' train whose headcode is " +
13504 MainHeadCode +
" and is formed from a service with headcode " + OtherHeadCode);
13510 if(ForwardEntryPtr->Command ==
"Fns")
13512 if(ReverseEntryPtr->
Command !=
"Sns")
13514 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns' event for the train whose headcode is " + MainHeadCode +
13515 " and forms a new service with headcode " + OtherHeadCode);
13522 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
13533 if(ForwardEntryPtr->Command ==
"jbo")
13535 if(ReverseEntryPtr->
Command !=
"Fjo")
13537 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fjo' event for the train whose headcode is " + MainHeadCode +
13538 " and is joined by a train with headcode " + OtherHeadCode);
13544 if(ForwardEntryPtr->Command ==
"Fjo")
13546 if(ReverseEntryPtr->
Command !=
"jbo")
13548 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'jbo' event for the train whose headcode is " + MainHeadCode +
13549 " and joins a train with headcode " + OtherHeadCode);
13556 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
13566 if(ForwardShuttleStart)
13569 if(!ReverseShuttleFinish)
13572 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + MainHeadCode +
13573 " from train whose headcode is " + OtherHeadCode +
", has to be Fns-sh, Frh-sh");
13579 if(ReverseShuttleStart)
13582 if(!ForwardShuttleFinish)
13585 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + OtherHeadCode +
13586 " from train whose headcode is " + MainHeadCode +
", has to be Fns-sh, Frh-sh");
13593 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
13605 bool MainRepeat =
false, OtherRepeat =
false;
13615 OtherRepeat =
true;
13618 if((MainRepeat && !OtherRepeat) || (!MainRepeat && OtherRepeat))
13620 SecondPassMessage(GiveMessages,
"Error in timetable - only one repeat is provided for the train whose headcode is " + MainHeadCode +
13621 " and the associated train with headcode " + OtherHeadCode);
13626 if(MainRepeat && OtherRepeat)
13632 SecondPassMessage(GiveMessages,
"Error in timetable - repeat items don't correspond for the train whose headcode is " + MainHeadCode +
13633 " and the associated train with headcode " + OtherHeadCode);
13655 while(Input[1] ==
' ')
13657 if(Input.Length() > 1)
13659 Input = Input.SubString(2, Input.Length() - 1);
13673 while(Input[Input.Length()] ==
' ')
13675 if(Input.Length() > 1)
13677 Input = Input.SubString(1, Input.Length() - 1);
13687 AnsiString Output =
"";
13688 bool DelimiterFound =
false;
13690 for(
int x = 1; x < Input.Length() + 1; x++)
13694 if(Input[x] ==
' ')
13699 if((Input[x] !=
',') && (Input[x] !=
';'))
13701 DelimiterFound =
false;
13702 Output = Output + Input[x];
13706 DelimiterFound =
true;
13707 Output = Output + Input[x];
13719 DelimiterFound =
false;
13720 for(
int x = Input.Length(); x > 0; x--)
13724 if(Input[x] ==
' ')
13729 if((Input[x] !=
',') && (Input[x] !=
';'))
13731 DelimiterFound =
false;
13732 Output = AnsiString(Input[x]) + Output;
13736 DelimiterFound =
true;
13737 Output = AnsiString(Input[x]) + Output;
13757 if((AVEntry0.
Command !=
"Snt") && (AVEntry0.
Command !=
"Snt-sh"))
13759 throw Exception(
"Error, first entry not 'Snt' or 'Snt-sh' in IsSNTEntryLocated");
13771 LocationName = LocRear;
13775 LocationName = LocFront;
13777 if(LocationName ==
"")
13803 AnsiString TimeLocLocationName;
13804 bool FoundFlag =
false;
13806 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
13821 if(TimeLocLocationName == LocationName)
13838 int RearPosition = 0, FrontPosition = 0, RearExitPos = 0;
13841 if(RearPosition < 0)
13848 if(FrontPosition < 0)
13859 for(
int x = 0; x < 4; x++)
13861 if(RearTrackElement.
Conn[x] == FrontPosition)
13876 TimetableMessage(GiveMessages,
"Front of train attempting to start on a continuation at: " + FrontElementStr);
13883 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + FrontElementStr);
13889 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + RearElementStr);
13894 if((RearType ==
Points) && (RearExitPos == 3))
13896 TimetableMessage(GiveMessages,
"Front of train attempting to start on element connected to diverging points at: " + RearElementStr);
13902 TimetableMessage(GiveMessages,
"Rear of train attempting to start on element connected to diverging points at: " + FrontElementStr);
13917 AnsiString(RearExitPos));
13928 int FrontPosition = RearTrackElement.
Conn[RearExitPos];
13930 int FrontEntryPos = RearTrackElement.
ConnLinkPos[RearExitPos];
13933 AnsiString RearName, FrontName;
13949 FrontName = FrontTrackElement.
ElementID;
13952 int LockedVectorNumber;
14122 "," + AnsiString(IncDigits));
14125 throw Exception(
"Error, last 2 characters not both digits and IncDigits > 0 in GetRepeatHeadCode");
14130 return(BaseHeadCode);
14132 int BaseDigits = BaseHeadCode.SubString(3, 2).ToInt();
14133 int NextRepeatDigits = BaseDigits + (IncDigits * RepeatNumber);
14135 while(NextRepeatDigits >= 100)
14137 NextRepeatDigits -= 100;
14139 AnsiString NextRepeatDigitsStr = AnsiString(NextRepeatDigits);
14141 if(NextRepeatDigitsStr.Length() < 2)
14143 NextRepeatDigitsStr = AnsiString(
'0') + NextRepeatDigitsStr;
14145 AnsiString NextRepeatHeadCode = BaseHeadCode.SubString(1, 2) + NextRepeatDigitsStr;
14148 return(NextRepeatHeadCode);
14156 AnsiString(RepeatNumber) +
"," + AnsiString(IncMinutes));
14157 TDateTime NextRepeatTime = BasicTime + TDateTime(((
double)(RepeatNumber * IncMinutes)) / 1440.0);
14160 return(NextRepeatTime);
14169 AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes));
14170 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
14171 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
14172 int RepeatSecs = RepeatMinutes * 60;
14174 if((ForwardSecs > (ReverseSecs - RepeatSecs + 10)) || (ForwardSecs < (ReverseSecs - RepeatSecs - 10)))
14209 NonRepeatingHeadCode);
14210 int ForwardCount = 0;
14211 int ReverseCount = 0;
14212 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
14222 if(TDEntry.
HeadCode == MainHeadCode)
14224 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14230 ForwardEntryPtr = &AVEntry;
14232 ForwardTDVectorNumber = x;
14237 if(ForwardCount == 0)
14240 throw Exception(
"Error, ForwardCount == 0 in CheckNonRepeatingShuttleLinksAndSetData after called with found values");
14242 if(ForwardCount > 1)
14244 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + NonRepeatingHeadCode +
" from a train whose headcode is " +
14254 if(TDEntry.
HeadCode == NonRepeatingHeadCode)
14256 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14263 ReverseEntryPtr = &AVEntry;
14264 ReverseTDVectorNumber = x;
14270 if(ReverseCount == 0)
14272 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + NonRepeatingHeadCode);
14277 if(ReverseCount > 1)
14279 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
14280 NonRepeatingHeadCode);
14285 if(((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh")) && (MainTrainDataPtr->
ActionVector.back().FormatType ==
Repeat))
14287 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle connecting train " + MainHeadCode +
" shouldn't have a repeat");
14292 if((ForwardEntryPtr->Command !=
"F-nshs") && (ForwardEntryPtr->Command !=
"Sns-fsh") && (MainTrainDataPtr->
ActionVector.back().FormatType !=
Repeat))
14294 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat item");
14299 if(ForwardEntryPtr->LocationName ==
"")
14301 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
14302 ". One or other service does not have a location set");
14309 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
14310 ". One or other service does not have a location set");
14315 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
14317 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + NonRepeatingHeadCode +
14318 " is at a different location to the referencing train " + MainHeadCode);
14323 if(ForwardEntryPtr->Command ==
"F-nshs")
14326 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
14328 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle in-link service " + MainHeadCode +
14329 " finish time not consistent with start time of shuttle service " + NonRepeatingHeadCode);
14335 if(ForwardEntryPtr->Command ==
"Fns-sh")
14339 MainTrainDataPtr->
ActionVector.back().RearStartOrRepeatMins, MainTrainDataPtr->
ActionVector.back().NumberOfRepeats))
14341 SecondPassMessage(GiveMessages,
"Error in timetable - service " + NonRepeatingHeadCode +
", which links out from shuttle service " + MainHeadCode +
14342 ", has the wrong start time. It should correspond to the finish time of the last shuttle.");
14348 if((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh"))
14351 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
14353 SecondPassMessage(GiveMessages,
"Error in timetable - the non repeating link service " + NonRepeatingHeadCode +
14354 " appears in the same sequence as the corresponding shuttle service " + MainHeadCode);
14372 if(ForwardEntryPtr->Command ==
"Sns-sh")
14374 if(ReverseEntryPtr->
Command !=
"F-nshs")
14376 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'F-nshs' event for the 'Sns-sh' train whose headcode is " +
14377 MainHeadCode +
" and is a new shuttle service formed from the service with headcode " + NonRepeatingHeadCode);
14383 if(ForwardEntryPtr->Command ==
"F-nshs")
14385 if(ReverseEntryPtr->
Command !=
"Sns-sh")
14387 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns-sh' event for the 'F-nshs' train whose headcode is " +
14388 MainHeadCode +
" and forms a new shuttle service with headcode " + NonRepeatingHeadCode);
14395 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
14406 if(ForwardEntryPtr->Command ==
"Sns-fsh")
14408 if(ReverseEntryPtr->
Command !=
"Fns-sh")
14411 "Error in timetable - unable to find a corresponding 'Fns-sh' event for the 'Sns-fsh' non-shuttle service whose headcode is " + MainHeadCode +
14412 " formed from a shuttle service with headcode " + NonRepeatingHeadCode);
14418 if(ForwardEntryPtr->Command ==
"Fns-sh")
14420 if(ReverseEntryPtr->
Command !=
"Sns-fsh")
14423 "Error in timetable - unable to find a corresponding 'Sns-fsh' event for the 'Fns-sh' shuttle service whose headcode is " + MainHeadCode +
14424 " and forms a new non-shuttle service with headcode " + NonRepeatingHeadCode);
14431 ForwardEntryPtr->NonRepeatingShuttleLinkEntryPtr = OtherTrainDataPtr;
14455 +
"," + AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes) +
"," + AnsiString(RepeatNumber));
14456 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
14457 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
14458 int RepeatSecs = RepeatMinutes * RepeatNumber * 60;
14460 if((ReverseSecs > (ForwardSecs + RepeatSecs + 10)) || (ReverseSecs < (ForwardSecs + RepeatSecs - 10)))
14484 throw Exception(
"Error - last entry in " + TDEntryPtr->
HeadCode +
" service is not a repeat - should have already found this error");
14487 AnsiString OriginalHeadCode = TDEntryPtr->
HeadCode;
14488 AnsiString LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
14490 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
14492 SecondPassMessage(GiveMessages,
"Error in timetable - last event in shuttle service " + TDEntryPtr->
HeadCode +
" is not 'Fns', 'Fns-sh' or 'Frh-sh'");
14497 while(LastActionCommand ==
"Fns")
14499 TDEntryPtr = (TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr;
14500 LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
14501 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
14504 "Error in timetable - last event in a continuation shuttle service (i.e links back to a shuttle) whose headcode is " + TDEntryPtr->
HeadCode +
14505 " is not 'Fns', 'Fns-sh' or 'Frh-sh'");
14512 if((TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr != ShuttleStartAddress)
14515 " is a shuttle finish, but it doesn't link back to the start of the original shuttle starting service " + OriginalHeadCode +
14516 ". The linking of two or more shuttles is not permitted.");
14536 ShowMessage(Message);
14554 ShowMessage(Message);
14593 AnsiString(ActionEventType) +
"," + LocationID);
14594 AnsiString BaseLog =
"", Prefix =
"", ErrorLog =
"", WarningStr =
"";
14599 Prefix =
" ERROR: ";
14602 Prefix =
" HELD: ";
14603 ErrorLog =
" can't enter railway, train obstructing entry position ";
14604 WarningStr =
" can't enter railway, train obstructing entry position ";
14609 Prefix =
" HELD: ";
14610 ErrorLog =
" can't enter railway, route set against it at entry position ";
14611 WarningStr =
" can't enter railway, route set against it at entry position ";
14616 Prefix =
" HELD: ";
14617 ErrorLog =
" can't be created, train obstructing ";
14618 WarningStr =
" can't be created, train obstructing ";
14623 Prefix =
" HELD: ";
14624 ErrorLog =
" can't be created on a locked route at ";
14625 WarningStr =
" can't be created on a locked route at ";
14630 Prefix =
" HELD: ";
14631 ErrorLog =
" can't enter on a locked route at ";
14632 WarningStr =
" can't enter on a locked route at ";
14637 Prefix =
" HELD: ";
14638 ErrorLog =
" can't be created, diverging points at ";
14639 WarningStr =
" can't be created, diverging points at ";
14644 ErrorLog =
" left railway unexpectedly at ";
14649 ErrorLog =
" left railway at an incorrect exit at ";
14654 ErrorLog =
" failed to split - location too short at ";
14655 WarningStr =
" failed to split, location too short at ";
14660 Prefix =
" HELD: ";
14661 ErrorLog =
" unable to split - other train obstructing at ";
14662 WarningStr =
" unable to split - other train obstructing at ";
14667 ErrorLog =
" stopped at buffers unexpectedly at position ";
14671 ErrorLog =
" failed to stop at ";
14676 ErrorLog =
" failed to split at ";
14681 ErrorLog =
" failed to be joined by other train at ";
14686 ErrorLog =
" failed to join other train at ";
14691 ErrorLog =
" failed to terminate at ";
14696 ErrorLog =
" failed to form new service at ";
14701 ErrorLog =
" failed to exit railway ";
14706 ErrorLog =
" failed to change direction at ";
14711 ErrorLog =
" failed to pass ";
14716 ErrorLog =
" facing buffers and unable to start at ";
14720 ErrorLog =
" DERAILED at position ";
14721 Prefix =
" DERAILMENT: ";
14726 ErrorLog =
" CRASHED INTO BUFFERS at ";
14727 Prefix =
" CRASH: ";
14732 ErrorLog =
" CRASHED INTO ROAD TRAFFIC AT A LEVEL CROSSING at ";
14733 Prefix =
" CRASH: ";
14738 ErrorLog =
" CRASHED INTO " + OtherHeadCode +
" at position ";
14739 Prefix =
" CRASH: ";
14743 else if(ActionEventType ==
FailSPAD)
14745 ErrorLog =
" PASSED SIGNAL AT DANGER at position ";
14746 Prefix =
" SPAD: ";
14751 ErrorLog =
"Signals reset ahead of train, route cancelled at position ";
14752 Prefix =
" SPAD RISK: ";
14757 ErrorLog =
" forced a route cancellation by occupying it incorrectly at ";
14761 Prefix =
" WARNING: ";
14762 ErrorLog =
" waiting to join " + OtherHeadCode +
" at ";
14763 WarningStr =
" waiting to join " + OtherHeadCode +
" at ";
14768 Prefix =
" WARNING: ";
14769 ErrorLog =
" waiting to be joined by " + OtherHeadCode +
" at ";
14770 WarningStr =
" waiting to be joined by " + OtherHeadCode +
" at ";
14808 std::ofstream OutFile(
"TrainData.csv");
14812 ShowMessage(
"Output file TrainData.csv failed to open");
14819 OutFile <<
"HeadCode" <<
',' <<
"Description" <<
',' <<
"StartSpeed" <<
',' <<
"MaxRunningSpeed" <<
',' <<
"NumberOfTrains" <<
'\n' <<
'\n';
14824 OutFile <<
',' <<
"FormatType" <<
',' <<
"EventTime" <<
',' <<
"ArrivalTime" <<
',' <<
"DepartureTime" <<
',' <<
"LocationName" <<
',' <<
"Command" <<
14825 ',' <<
"OtherHeadCode" <<
',' <<
"LinkedTrainEntryPtr" <<
',' <<
"RearStartOrRepeatMins" <<
',' <<
"FrontStartOrRepeatDigits" <<
',' <<
14826 "RepeatNumber" <<
'\n' <<
'\n';
14827 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14830 AnsiString TimetableEntryTypeStr;
14836 TimetableEntryTypeStr =
"NoFormat";
14842 TimetableEntryTypeStr =
"TimeLoc";
14848 TimetableEntryTypeStr =
"TimeTimeLoc";
14854 TimetableEntryTypeStr =
"TimeCmd";
14860 TimetableEntryTypeStr =
"StartNew";
14866 TimetableEntryTypeStr =
"TimeCmdHeadCode";
14872 TimetableEntryTypeStr =
"FinRemHere";
14878 TimetableEntryTypeStr =
"FNSShuttle";
14884 TimetableEntryTypeStr =
"SNTShuttle";
14890 TimetableEntryTypeStr =
"SNSShuttle";
14896 TimetableEntryTypeStr =
"SNSNonRepeatFromShuttle";
14902 TimetableEntryTypeStr =
"FSHNewService";
14908 TimetableEntryTypeStr =
"Repeat";
14914 TimetableEntryTypeStr =
"Default";
14925 OutFile <<
',' <<
',' <<
"Mass" <<
',' <<
"MaxBrakeRate" <<
',' <<
"PowerAtRail" <<
',' <<
"TrainID" <<
',' <<
"RunningEntry" <<
'\n' <<
'\n';
14926 for(
unsigned int y = 0; y <
TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
14929 AnsiString RunningEntryStr;
14935 RunningEntryStr =
"NotStarted";
14941 RunningEntryStr =
"Running";
14947 RunningEntryStr =
"Exited";
14951 OutFile <<
',' <<
',' << TOD.
TrainID <<
',' << RunningEntryStr.c_str() <<
',' <<
'\n';
14968 ShowMessage(Message);
14969 BaseTime = TDateTime::CurrentDateTime();
14983 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
14996 TTrain *NewTrain =
new TTrain(1, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
14998 for(
int x = 0; x < NumberOfTrains; x++)
15000 *NewTrain =
TTrain(2, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
15020 int NumberOfTrains;
15027 for(
int x = 0; x < NumberOfTrains; x++)
15064 for(
int x = 0; x < LockedRouteVectorSize; x++)
15071 LockedRouteObject.
LockStartTime = TDateTime(LockStartTimeDouble);
15082 int LockedRouteVectorSize;
15089 for(
int x = 0; x < LockedRouteVectorSize; x++)
15147 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
15155 ContinuationAutoSigObject.
PassoutTime = TDateTime(PassoutTimeDouble);
15166 int ContinuationAutoSigVectorSize;
15173 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
15243 if(AVFirstEntry.
Command ==
"Snt")
15267 CTEMMP.second = CTEEntry;
15274 throw Exception(
"Error, Last ActionVectorEntry not a repeat in BuildContinuationTrainExpectationMultiMap");
15282 CTEMMP.second = CTEEntry;
15303 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
15320 if((VecPos < 0) || (VecPos >= (
int)
TrainVector.size()))
15322 throw Exception(
"Out of Range Error, vector size: " + AnsiString(
TrainVector.size()) +
", VecPos: " + AnsiString(VecPos) +
" in TrainVectorAt");
15333 AnsiString RetStr =
"", PartStr =
"";
15448 AnsiString TTFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
15452 TTFileName = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
15454 AnsiString ShortTTName =
"";
15456 for(
int x = TTFileName.Length(); x > 0; x--)
15458 if(TTFileName[x] ==
'\\')
15460 ShortTTName = TTFileName.SubString(x + 1, TTFileName.Length() - x - 4);
15465 ShowMessage(
"Creates two timetables named " + ShortTTName +
15466 " in the 'Formatted timetables' folder, one in service order in '.csv' format, and one in chronological order in '.txt' format");
15468 Screen->Cursor = TCursor(-11);
15470 AnsiString FormatNoDPStr =
"#######0";
15471 AnsiString TableTitle =
"", TimetableTimeStr =
"", MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"", FirstHeadCode =
"", Header =
"";
15474 TableTitle =
"Railway: " + RailwayTitle +
"; Timetable: " + TimetableTitle +
"; Start time: " + TimetableTimeStr;
15481 MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"";
15483 if(TrainDataEntry.
Mass > 0)
15485 MassStr =
"; Mass " + AnsiString::FormatFloat(FormatNoDPStr, ((
double)TrainDataEntry.
Mass) / 1000) +
"Te; ";
15489 PowerStr =
"Power " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
PowerAtRail / 1000 / 0.8) +
"kW; ";
15493 BrakeStr =
"Brake force " + AnsiString::FormatFloat(FormatNoDPStr, (TrainDataEntry.
MaxBrakeRate * TrainDataEntry.
Mass / 9810)) +
"Te; ";
15497 MaxSpeedStr =
"Maximum speed " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
MaxRunningSpeed) +
" km/h";
15499 FirstHeadCode = TrainDataEntry.
HeadCode;
15500 int IncDigits = 0, IncMinutes = 0;
15502 if(!ActionVector.empty())
15504 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
15506 IncDigits = ActionVector.at(ActionVector.size() - 1).FrontStartOrRepeatDigits;
15507 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
15515 if((TrainDataEntry.
Description !=
"") && (MassStr !=
""))
15517 OneTTLine.
Header = TrainDataEntry.
Description + MassStr + PowerStr + BrakeStr + MaxSpeedStr;
15525 for(
unsigned int z = 0; z < ActionVector.size(); z++)
15530 AnsiString PartStr =
"", TimeStr =
"";
15547 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
15551 PartStr =
"Created at " + ActionVectorEntry.
LocationName;
15561 PartStr =
"Enters at " + LocName;
15574 PartStr =
"Created at " + LocName;
15588 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
15593 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
15599 else if(ActionVectorEntry.
Command ==
"Sfs")
15601 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" split from";
15605 else if(ActionVectorEntry.
Command ==
"Sns")
15607 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
15615 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
15621 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
15629 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
15632 AnsiString FirstHeadCode = TDE->
HeadCode;
15636 TimeStr =
GetRepeatHeadCode(36, FirstHeadCode, LastRepeatNumber, IncrementalDigits) +
" at " +
15648 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
15650 OneTTEntry.
Action = PartStr;
15651 OneTTEntry.
Time = TimeStr;
15653 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
15658 PartStr =
"Arrives & departs " + ActionVectorEntry.
LocationName;
15664 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
15669 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
15677 else if(ActionVectorEntry.
Command ==
"jbo")
15679 PartStr =
"Joined at " + ActionVectorEntry.
LocationName +
" by";
15683 else if(ActionVectorEntry.
Command ==
"fsp")
15685 PartStr =
"Splits from front at " + ActionVectorEntry.
LocationName +
" to form";
15689 else if(ActionVectorEntry.
Command ==
"rsp")
15691 PartStr =
"Splits from rear at " + ActionVectorEntry.
LocationName +
" to form";
15695 else if(ActionVectorEntry.
Command ==
"cdt")
15697 PartStr =
"Changes direction at " + ActionVectorEntry.
LocationName;
15703 if(ActionVectorEntry.
Command ==
"Fns")
15705 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
15709 else if(ActionVectorEntry.
Command ==
"F-nshs")
15711 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
15717 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service ";
15724 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
15730 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
15737 PartStr =
"Terminates shuttle service at " + ActionVectorEntry.
LocationName;
15742 else if(ActionVectorEntry.
Command ==
"Frh")
15744 PartStr =
"Terminates at " + ActionVectorEntry.
LocationName;
15749 if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
15753 else if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
15763 else if(ActionVectorEntry.
Command ==
"Fer")
15765 AnsiString AllowedExits;
15769 else if(ActionVectorEntry.
Command ==
"Fjo")
15771 PartStr =
"At " + ActionVectorEntry.
LocationName +
" joins";
15780 OneTTEntry.
Action = PartStr;
15781 OneTTEntry.
Time = TimeStr;
15788 AllTTTrains->push_back(OneTTLine);
15792 std::ofstream TTFile(TTFileName.c_str());
15796 StopTTClockMessage(64,
"Formatted timetable file failed to open - can't be created");
15797 delete AllTTTrains;
15832 TTFile << TableTitle.c_str() <<
'\n' <<
'\n';
15833 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
15835 TTFile << AllTTTrains->at(x).Header.c_str();
15838 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
15840 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
15842 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str() <<
',';
15846 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str();
15849 TTFile <<
'\n' <<
'\n';
15851 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.size(); z++)
15853 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.at(z).Action.c_str() <<
',';
15854 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
15856 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
15858 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str() <<
',';
15862 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str();
15867 TTFile <<
'\n' <<
'\n';
15872 AnsiString TTFileName2 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
15874 TTFileName2 = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName2 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".txt";
15876 std::ofstream TTFile2(TTFileName2.c_str());
15880 StopTTClockMessage(67,
"Chronological timetable file failed to open - can't be created");
15881 delete AllTTTrains;
15885 typedef std::multimap<AnsiString, AnsiString>TAnsiMultiMap;
15886 std::multimap<AnsiString, AnsiString>::iterator AMMIT;
15887 std::pair<AnsiString, AnsiString>AnsiMultiMapEntry;
15889 TAnsiMultiMap *TAMM =
new TAnsiMultiMap;
15894 TTFile2 << TableTitle.c_str() <<
'\n' <<
'\n';
15895 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
15897 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
15899 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.size(); z++)
15901 bool GiveMessagesFalse =
false;
15902 AnsiString TimeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time;
15903 AnsiString HeadCodeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode;
15904 AnsiString ActionString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Action;
15909 AnsiString OtherHeadCode = TimeString.SubString(1, 4);
15910 TimeString = TimeString.SubString(9, 5);
15911 ActionString +=
" " + OtherHeadCode;
15913 if(TimeString.SubString(1, 7) ==
"End at ")
15916 TimeString = TimeString.SubString(8, 5);
15918 AnsiString OneLine = TimeString +
' ' + HeadCodeString +
' ' + ActionString +
'\n';
15919 AnsiMultiMapEntry.first = TimeString;
15920 AnsiMultiMapEntry.second = OneLine;
15921 TAMM->insert(AnsiMultiMapEntry);
15926 for(AMMIT = TAMM->begin(); AMMIT != TAMM->end(); AMMIT++)
15928 TTFile2 << (AMMIT->second).c_str();
15930 delete AllTTTrains;
15939 bool AtLocChecked,
bool DirChecked,
int ArrRange,
int DepRange)
15943 bool AnalysisError =
false;
15944 AnsiString SequenceLog =
"SequenceLog\n";
15986 TTrainDataVector::iterator TDVIt, TDVCopyIt;
15988 int IteratorNumber = 0;
15989 AnsiString AnsiSuffix =
"";
15994 for(TDVCopyIt = TrainDataVectorCopy.begin() + IteratorNumber; TDVCopyIt != TrainDataVectorCopy.end(); TDVCopyIt++)
15996 if(TDVCopyIt->ServiceReference == TDVIt->ServiceReference)
15999 AnsiSuffix = AnsiString(Suffix);
16000 TDVCopyIt->ServiceReference = TDVIt->ServiceReference +
"/" + AnsiSuffix;
16004 SequenceLog +=
"1\n";
16007 std::pair<AnsiString, TServiceCallingLocsList> AllServiceCallingLocsEntry;
16008 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
16013 ServiceCallingLocsList.clear();
16014 if(ActionVector.empty())
16018 if(ActionVector.at(0).SignallerControl)
16022 for(
unsigned int z = 0; z < ActionVector.size(); z++)
16040 int HLoc = TE.
HLoc;
16041 int VLoc = TE.
VLoc;
16042 AnsiString HString;
16043 AnsiString VString;
16046 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
16050 HString = AnsiString(HLoc);
16054 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
16058 VString = AnsiString(VLoc);
16060 ServiceCallingLocsList.push_back(HString +
'-' + VString);
16083 else if(AVE.
Command ==
"cdt")
16085 if(ActionVector.at(z-1).SequenceType ==
Start)
16089 else if(ActionVector.at(z+1).SequenceType ==
Finish)
16096 ServiceCallingLocsList.push_back(
"%%%" + TimeString);
16105 ServiceCallingLocsList.push_back(LName);
16109 int HLoc = TE.
HLoc;
16110 int VLoc = TE.
VLoc;
16111 AnsiString HString;
16112 AnsiString VString;
16115 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
16119 HString = AnsiString(HLoc);
16123 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
16127 VString = AnsiString(VLoc);
16129 ServiceCallingLocsList.push_back(HString +
'-' + VString);
16133 AllServiceCallingLocsEntry.second = ServiceCallingLocsList;
16137 SequenceLog +=
"2\n";
16167 ShowMessage(
"Unable to create a program-readable timetable - please check the timetable file validity");
16173 bool NumPlatsAtThisLocCalculated =
false, ArrivalsPrinted =
false, DeparturesPrinted =
false, AtLocsPrinted =
false;
16174 AnsiString PreviousService =
"", PreviousServiceAndRepeatNumTotalOutput =
"", BasicTime =
"", MinuteString =
"", LastAnsiTime =
"";
16175 int NumTrains = 0, NumPlats = 0, LastFrhCount = 0, FrhCount = 0, NumTrainsAtLoc = 0;
16177 SequenceLog +=
"3\n";
16179 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
16184 TDateTime LastTDTime;
16185 int IncMinutes = 0;
16187 if(ActionVector.empty())
16191 if(ActionVector.at(0).SignallerControl)
16195 if(AVLast->FormatType ==
Repeat)
16197 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
16205 if(AVLast->ArrivalTime != TDateTime(-1))
16207 LastTDTime = AVLast->ArrivalTime;
16209 else if(AVLast->EventTime != TDateTime(-1))
16211 LastTDTime = AVLast->EventTime;
16230 SequenceLog +=
"4\n";
16262 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
16267 int IncMinutes = 0;
16269 if(ActionVector.empty())
16273 if(ActionVector.at(0).SignallerControl)
16277 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
16279 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
16281 for(
int y = 0; y < NumTrains; y++)
16295 for(
unsigned int z = 0; z < ActionVector.size(); z++)
16310 LocServiceTimesVector.push_back(TLSTEntry);
16313 AnsiString IncTime =
"", FoundStopTime =
"";
16314 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
16316 if(ActionVector.at(a).FormatType ==
TimeLoc)
16321 if(ActionVector.at(a).SequenceType ==
Finish)
16327 if(FoundStopTime ==
"")
16329 throw Exception(
"Failure to determine FoundStopTime for located Snt");
16331 int WhileCount = 0;
16340 if(IncTime >= FoundStopTime)
16344 LocServiceTimesVector.push_back(TLSTEntry);
16345 if(WhileCount > 2000)
16347 throw Exception(
"While loop failed to break in 2000 loops for located Snt");
16360 int HLoc = TE.
HLoc;
16361 int VLoc = TE.
VLoc;
16362 AnsiString HString;
16363 AnsiString VString;
16366 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
16370 HString = AnsiString(HLoc);
16374 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
16378 VString = AnsiString(VLoc);
16380 TLSTEntry.
Location = HString +
'-' + VString;
16384 LocServiceTimesVector.push_back(TLSTEntry);
16392 LocServiceTimesVector.push_back(TLSTEntry);
16394 AnsiString IncTime =
"", FoundStopTime =
"";
16395 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
16397 if(ActionVector.at(a).FormatType ==
TimeLoc)
16402 if(ActionVector.at(a).SequenceType ==
Finish)
16408 if(FoundStopTime ==
"")
16410 throw Exception(
"Failure to determine FoundStopTime for SequenceType == Start");
16412 int WhileCount = 0;
16421 if(IncTime >= FoundStopTime)
16425 LocServiceTimesVector.push_back(TLSTEntry);
16426 if(WhileCount > 2000)
16428 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == Start");
16438 bool SkipAddingMinutes =
false;
16441 LocServiceTimesVector.push_back(TLSTEntry);
16443 AnsiString IncTime =
"", FoundStopTime =
"";
16444 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
16446 if(ActionVector.at(a).FormatType ==
TimeLoc)
16451 if(ActionVector.at(a).SequenceType ==
Finish)
16454 if((a <= (z + 2)) && (FoundStopTime == TLSTEntry.
ArrTime) && ((ActionVector.at(a).LinkedTrainEntryPtr > 0) || (ActionVector.at(a).NonRepeatingShuttleLinkEntryPtr > 0)))
16458 LocServiceTimesVector.pop_back();
16459 SkipAddingMinutes =
true;
16464 if(FoundStopTime ==
"")
16466 throw Exception(
"Failure to determine FoundStopTime for SequenceType == Start");
16468 if(!SkipAddingMinutes)
16470 int WhileCount = 0;
16479 if(IncTime >= FoundStopTime)
16483 LocServiceTimesVector.push_back(TLSTEntry);
16484 if(WhileCount > 2000)
16486 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == Start");
16495 if((TLSTEntry.
Location == LocServiceTimesVector.back().Location) && (TLSTEntry.
ServiceAndRepeatNum == LocServiceTimesVector.back().ServiceAndRepeatNum))
16497 if(TLSTEntry.
DepTime == LocServiceTimesVector.back().ArrTime)
16499 TLSTEntry.
ArrTime = LocServiceTimesVector.back().ArrTime;
16500 LocServiceTimesVector.pop_back();
16501 LocServiceTimesVector.push_back(TLSTEntry);
16506 LocServiceTimesVector.push_back(TLSTEntry);
16512 LocServiceTimesVector.push_back(TLSTEntry);
16531 LocServiceTimesVector.push_back(TLSTEntry);
16535 AnsiString TempDepTime = TLSTEntry.
DepTime;
16537 LocServiceTimesVector.push_back(TLSTEntry);
16539 while(TLSTEntry.
AtLocTime < TempDepTime)
16544 TLSTEntry.
DepTime = TempDepTime;
16545 LocServiceTimesVector.push_back(TLSTEntry);
16549 LocServiceTimesVector.push_back(TLSTEntry);
16560 LocServiceTimesVector.push_back(TLSTEntry);
16563 LocServiceTimesVector.push_back(TLSTEntry);
16580 AnsiString HString;
16581 AnsiString VString;
16584 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
16588 HString = AnsiString(HLoc);
16592 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
16596 VString = AnsiString(VLoc);
16598 TLSTEntry.
Location = HString +
'-' + VString;
16600 LocServiceTimesVector.push_back(TLSTEntry);
16605 AnsiString FrhTime;
16606 if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
16610 else if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
16618 LocServiceTimesVector.push_back(TLSTEntry);
16624 LocServiceTimesVector.push_back(TLSTEntry);
16629 else if(AVE.
Command ==
"Frh-sh")
16631 if(y == NumTrains - 1)
16637 LocServiceTimesVector.push_back(TLSTEntry);
16643 LocServiceTimesVector.push_back(TLSTEntry);
16656 SequenceLog +=
"5\n";
16684 TLocServiceTimesVector::iterator Ptr1, Ptr2;
16687 AnsiString TTFileName3 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
16688 TTFileName3 = CurDir +
"\\Formatted timetables\\Conflict Analysis " + TTFileName3 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
16690 std::ofstream TTFile3(TTFileName3.c_str());
16694 ShowMessage(
"Conflict Analysis file failed to open - can't be created");
16698 if(LocServiceTimesVector.empty())
16700 ShowMessage(
"No timetabled services found");
16702 DeleteFile(TTFileName3);
16706 TTFile3 <<
"Timetable analysis for timetable: '" + TimetableTitle +
"' in conjunction with railway: '" + RailwayTitle +
"'\n";
16707 TTFile3 <<
"See user manual or on-screen help section 5.12 for detailed information.\n\n\n";
16708 SequenceLog +=
"6\n";
16757 Ptr1 = LocServiceTimesVector.begin();
16759 while(Ptr2 != LocServiceTimesVector.end())
16761 while(Ptr2->Location == Ptr1->Location)
16764 if(Ptr2 == LocServiceTimesVector.end())
16771 if(Ptr2 != LocServiceTimesVector.end())
16779 TTFile3 <<
"Arrival & pass analysis: an asterisk means that the number of same approach code arrivals and passes is equal to or greater than the number of platforms.\n";
16780 TTFile3 <<
"If the total number of arrivals and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
16781 MinuteString =
" minutes";
16782 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
16785 MinuteString =
" minute";
16787 TTFile3 <<
"Location,Number of,Number of,Services arriving within " << AnsiString(ArrRange) << MinuteString <<
" with their arrival times and approach codes\n";
16788 TTFile3 <<
",Platforms,Trains\n\n";
16790 Ptr1 = LocServiceTimesVector.begin();
16792 while(Ptr2 != LocServiceTimesVector.end())
16794 PreviousService =
"";
16795 NumTrainsAtLoc = 0;
16796 ServiceAndRepeatNumTotal =
"";
16798 NumPlatsAtThisLocCalculated =
false;
16800 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
16802 PreviousService =
"";
16803 NumTrainsAtLoc = 0;
16804 ServiceAndRepeatNumTotal =
"";
16806 NumPlatsAtThisLocCalculated =
false;
16810 if(Ptr2 == LocServiceTimesVector.end())
16815 if(Ptr2 == LocServiceTimesVector.end())
16819 while(Ptr2->Location == Ptr1->Location)
16821 PreviousService =
"";
16822 NumTrainsAtLoc = 0;
16823 ServiceAndRepeatNumTotal =
"";
16824 BasicTime = Ptr1->ArrTime;
16825 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
16829 while(!
WithinTimeRange(0, BasicTime, Ptr2->ArrTime, ArrRange) || ((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
"")))
16831 BasicTime = Ptr2->ArrTime;
16834 if(Ptr2 == LocServiceTimesVector.end())
16838 if(Ptr2->Location != Ptr1->Location)
16843 if(Ptr2 == LocServiceTimesVector.end())
16847 if(Ptr2->Location != Ptr1->Location)
16853 if((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
""))
16857 if(!NumPlatsAtThisLocCalculated)
16860 NumPlatsAtThisLocCalculated =
true;
16862 if(Ptr1->ServiceAndRepeatNum != PreviousService)
16864 if(ServiceAndRepeatNumTotal ==
"")
16866 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
16867 NumTrainsAtLoc = 1;
16871 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
16874 PreviousService = Ptr2->ServiceAndRepeatNum;
16875 if(ServiceAndRepeatNumTotal ==
"")
16877 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
16878 NumTrainsAtLoc = 1;
16882 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
16886 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(2, BasicTime, Ptr2->ArrTime, ArrRange)))
16888 int MaxNumberOfSameDirections = 0;
16889 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
true, AnalysisError, MaxNumberOfSameDirections);
16894 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
16898 AnsiString Asterisk =
"";
16899 if(MaxNumberOfSameDirections >= NumPlats)
16904 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
16905 ArrivalsPrinted =
true;
16906 ServiceAndRepeatNumTotal =
"";
16908 if(Ptr2 == LocServiceTimesVector.end())
16912 if(Ptr2->Location != Ptr1->Location)
16917 if(Ptr2 == LocServiceTimesVector.end())
16923 if(!ArrivalsPrinted)
16925 TTFile3 <<
"Nothing to report for arrivals";
16930 SequenceLog +=
"7\n";
16935 Ptr1 = LocServiceTimesVector.begin();
16937 while(Ptr2 != LocServiceTimesVector.end())
16939 while(Ptr2->Location == Ptr1->Location)
16942 if(Ptr2 == LocServiceTimesVector.end())
16949 if(Ptr2 != LocServiceTimesVector.end())
16956 TTFile3 <<
"Departure & pass analysis: an asterisk means that the number of same exit code departures and passes is equal to or greater than the number of platforms.\n";
16957 TTFile3 <<
"If the total number of departures and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
16958 MinuteString =
" minutes";
16959 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
16962 MinuteString =
" minute";
16964 TTFile3 <<
"Location,Number of,Number of,Services departing within " << AnsiString(DepRange) << MinuteString <<
" with their departure times and exit codes\n";
16965 TTFile3 <<
",Platforms,Trains\n\n";
16967 Ptr1 = LocServiceTimesVector.begin();
16969 while(Ptr2 != LocServiceTimesVector.end())
16971 PreviousService =
"";
16972 NumTrainsAtLoc = 0;
16973 ServiceAndRepeatNumTotal =
"";
16975 NumPlatsAtThisLocCalculated =
false;
16977 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
16979 PreviousService =
"";
16980 NumTrainsAtLoc = 0;
16981 ServiceAndRepeatNumTotal =
"";
16983 NumPlatsAtThisLocCalculated =
false;
16987 if(Ptr2 == LocServiceTimesVector.end())
16992 if(Ptr2 == LocServiceTimesVector.end())
16996 while(Ptr2->Location == Ptr1->Location)
16998 PreviousService =
"";
16999 NumTrainsAtLoc = 0;
17000 ServiceAndRepeatNumTotal =
"";
17001 BasicTime = Ptr1->DepTime;
17002 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
17006 while(!
WithinTimeRange(3, BasicTime, Ptr2->DepTime, DepRange) || ((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
"")))
17008 BasicTime = Ptr2->DepTime;
17011 if(Ptr2 == LocServiceTimesVector.end())
17015 if(Ptr2->Location != Ptr1->Location)
17020 if(Ptr2 == LocServiceTimesVector.end())
17024 if(Ptr2->Location != Ptr1->Location)
17030 if((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
""))
17034 if(!NumPlatsAtThisLocCalculated)
17037 NumPlatsAtThisLocCalculated =
true;
17039 if(Ptr1->ServiceAndRepeatNum != PreviousService)
17041 if(ServiceAndRepeatNumTotal ==
"")
17043 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
17044 NumTrainsAtLoc = 1;
17048 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
17051 PreviousService = Ptr2->ServiceAndRepeatNum;
17052 if(ServiceAndRepeatNumTotal ==
"")
17054 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
17055 NumTrainsAtLoc = 1;
17059 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
17063 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(5, BasicTime, Ptr2->DepTime, DepRange)))
17065 int MaxNumberOfSameDirections = 0;
17066 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(3, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
false, AnalysisError, MaxNumberOfSameDirections);
17071 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
17075 AnsiString Asterisk =
"";
17076 if(MaxNumberOfSameDirections >= NumPlats)
17081 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
17082 DeparturesPrinted =
true;
17083 ServiceAndRepeatNumTotal =
"";
17085 if(Ptr2 == LocServiceTimesVector.end())
17089 if(Ptr2->Location != Ptr1->Location)
17094 if(Ptr2 == LocServiceTimesVector.end())
17100 if(!DeparturesPrinted)
17102 TTFile3 <<
"Nothing to report for departures";
17107 SequenceLog +=
"8\n";
17114 Ptr1 = LocServiceTimesVector.begin();
17116 while(Ptr2 != LocServiceTimesVector.end())
17118 while(Ptr2->Location == Ptr1->Location)
17121 if(Ptr2 == LocServiceTimesVector.end())
17128 if(Ptr2 != LocServiceTimesVector.end())
17135 TTFile3 <<
"Trains present at location analysis: an asterisk means that the number of trains at the location is greater than the number of platforms.\n\n";
17136 TTFile3 <<
"Location,Number of,Number of,Time,Services at the location at that time\n";
17137 TTFile3 <<
",Platforms,Trains,\n\n";
17138 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
17139 Ptr1 = LocServiceTimesVector.begin();
17141 while(Ptr2 != LocServiceTimesVector.end())
17143 PreviousService =
"";
17144 ServiceAndRepeatNumTotal =
"";
17145 NumTrainsAtLoc = 0;
17147 NumPlatsAtThisLocCalculated =
false;
17149 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
17151 PreviousService =
"";
17152 ServiceAndRepeatNumTotal =
"";
17153 NumTrainsAtLoc = 0;
17155 NumPlatsAtThisLocCalculated =
false;
17159 if(Ptr2 == LocServiceTimesVector.end())
17164 if(Ptr2 == LocServiceTimesVector.end())
17168 while(Ptr2->Location == Ptr1->Location)
17170 if(Ptr1->FrhMarker ==
"Frh")
17173 Ptr1->FrhMarker =
"FrhCounted";
17175 PreviousService =
"";
17176 NumTrainsAtLoc = 0;
17177 ServiceAndRepeatNumTotal =
"";
17178 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
17182 while((Ptr2->AtLocTime != Ptr1->AtLocTime) || ((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
"")))
17185 if(Ptr1->FrhMarker ==
"Frh")
17188 Ptr1->FrhMarker =
"FrhCounted";
17191 if(Ptr2 == LocServiceTimesVector.end())
17195 if(Ptr2->Location != Ptr1->Location)
17200 if(Ptr2 == LocServiceTimesVector.end())
17204 if(Ptr2->Location != Ptr1->Location)
17208 while(Ptr2->AtLocTime == Ptr1->AtLocTime)
17210 if((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
""))
17214 if(!NumPlatsAtThisLocCalculated)
17217 NumPlatsAtThisLocCalculated =
true;
17219 if(Ptr1->ServiceAndRepeatNum != PreviousService)
17221 if(ServiceAndRepeatNumTotal ==
"")
17223 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum;
17224 NumTrainsAtLoc = 1;
17228 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum;
17231 PreviousService = Ptr2->ServiceAndRepeatNum;
17232 if(ServiceAndRepeatNumTotal ==
"")
17234 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum;
17235 NumTrainsAtLoc = 1;
17239 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum;
17242 if(Ptr1->FrhMarker ==
"Frh")
17245 Ptr1->FrhMarker =
"FrhCounted";
17248 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (Ptr2->AtLocTime != Ptr1->AtLocTime))
17252 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTAtLoc(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc);
17254 if((NumTrainsAtLoc > 1) && ((FrhCount < NumTrainsAtLoc) || (FrhCount != LastFrhCount)))
17256 AnsiString Asterisk =
"";
17257 if(NumTrainsAtLoc > NumPlats)
17264 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
17266 else if(FrhCount == 1)
17268 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (1 remains here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
17272 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (" << FrhCount <<
" remain here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
17274 LastFrhCount = FrhCount;
17275 PreviousServiceAndRepeatNumTotalOutput = ServiceAndRepeatNumTotalOutput;
17276 AtLocsPrinted =
true;
17277 ServiceAndRepeatNumTotal =
"";
17280 if(Ptr2 == LocServiceTimesVector.end())
17284 if(Ptr2->Location != Ptr1->Location)
17289 if(Ptr2 == LocServiceTimesVector.end())
17297 TTFile3 <<
"Nothing to report for trains at locations";
17302 SequenceLog +=
"9\n";
17332 TTrainDataEntry SingleServiceEntry, PartServiceEntry, NewPartServiceEntry, TempEntry;
17337 TTFile3 <<
"Train direction analysis - consisting of train facing directions on creation and possible missing or unexpected changes of direction:\n\n";
17338 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
17346 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
17348 SingleServiceEntry = TDE;
17350 for(
unsigned int y = 0; y < SSAV.size(); y++)
17352 if((SSAV.at(y).Command ==
"Fjo") || (SSAV.at(y).Command ==
"Frh") || (SSAV.at(y).Command ==
"Fer") || (SSAV.at(y).Command ==
"Frh-sh"))
17354 SingleServiceVector.push_back(SingleServiceEntry);
17357 else if((SSAV.at(y).Command ==
"fsp") || (SSAV.at(y).Command ==
"rsp"))
17359 PartServiceEntry = TDE;
17361 for(
unsigned int z = 0; z <= y; z++)
17366 PartServiceEntry.
ActionVector.at(z).Command =
"chr-sp";
17367 PartServiceEntry.
ActionVector.at(z).OtherHeadCode = PartServiceEntry.
ActionVector.at(z).LinkedTrainEntryPtr->ServiceReference;
17370 PartServiceVector.push_back(PartServiceEntry);
17371 if(SSAV.at(y).Command ==
"fsp")
17373 SSAV.at(y).Command =
"Front split - original service continues below";
17374 SSAV.at(y).OtherHeadCode =
"";
17376 if(SSAV.at(y).Command ==
"rsp")
17378 SSAV.at(y).Command =
"Rear split - original service continues below";
17379 SSAV.at(y).OtherHeadCode =
"";
17383 else if(SSAV.at(y).Command ==
"Fns")
17385 SSAV.at(y).Command =
"chr-Fns";
17386 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
17387 PartServiceVector.push_back(SingleServiceEntry);
17390 else if(SSAV.at(y).Command ==
"Fns-sh")
17392 SSAV.at(y).Command =
"chr-Fns-sh";
17393 SSAV.at(y).OtherHeadCode = SSAV.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
17394 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
17395 PartServiceVector.push_back(SingleServiceEntry);
17398 else if(SSAV.at(y).Command ==
"F-nshs")
17400 SSAV.at(y).Command =
"chr-F-nshs";
17401 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
17402 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
17403 PartServiceVector.push_back(SingleServiceEntry);
17409 SequenceLog +=
"10\n";
17413 AnsiString NextRef;
17414 while(!PartServiceVector.empty())
17416 PartServiceEntry = PartServiceVector.at(0);
17417 for(
unsigned int y = 0; y < PartServiceEntry.
ActionVector.size(); y++)
17419 if(PartServiceEntry.
ActionVector.at(y).Command.SubString(1,3) ==
"chr")
17421 NextRef = PartServiceEntry.
ActionVector.at(y).OtherHeadCode;
17425 bool FinishType =
true, FoundFlag =
false;
17432 for(
unsigned int y = 1; y < TempEntry.
ActionVector.size(); y++)
17436 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17440 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17446 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17447 SingleServiceVector.push_back(PartServiceVector.at(0));
17448 PartServiceVector.erase(&PartServiceVector.at(0));
17453 NewPartServiceEntry = PartServiceVector.at(0);
17457 PartServiceVector.push_back(NewPartServiceEntry);
17460 TempEntry.
ActionVector.at(y).Command =
"Front split - original service continues below";
17465 TempEntry.
ActionVector.at(y).Command =
"Rear split - original service continues below";
17468 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17470 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns")
17473 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
17475 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17478 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns-sh")
17481 TempEntry.
ActionVector.at(y).OtherHeadCode = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
17482 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
17483 NextRef = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
17484 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17487 else if(TempEntry.
ActionVector.at(y).Command ==
"F-nshs")
17491 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
17492 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
17493 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17501 SequenceLog += +
"11\n";
17502 throw Exception(
"Unable to find service reference " + NextRef +
" Last ref checked = " + TempEntry.
ServiceReference);
17506 if(!PartServiceVector.empty())
17508 SequenceLog +=
"12\n";
17509 throw Exception(
"PartServiceVector should be empty here - size = " + PartServiceVector.size());
17511 SequenceLog +=
"13\n";
17556 bool BufferFacingUnReportedFlag =
true;
17557 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
17563 SequenceLog +=
"13a\n";
17564 throw Exception(
"Repeat entry present in SingleServiceVector at position " + x);
17567 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
17569 bool BufferFlag =
false;
17570 int FrontTVPos = AV.at(0).FrontStartOrRepeatDigits;
17571 int RearTVPos = AV.at(0).RearStartOrRepeatMins;
17572 AnsiString FrontLocName = AV.at(0).LocationName;
17573 int NextEntryPos, NextExitPos;
17576 if(ThisElement.
Conn[0] == RearTVPos)
17580 else if(ThisElement.
Conn[1] == RearTVPos)
17584 else if(ThisElement.
Conn[2] == RearTVPos)
17588 else if(ThisElement.
Conn[3] == RearTVPos)
17600 if(ThisElement.
Conn[ThisExitPos] == -1)
17602 SequenceLog =
"13b\n";
17603 throw Exception(
"ThisElement connects to -1 for " + TDE.
ServiceReference);
17606 NextEntryPos = ThisElement.
ConnLinkPos[ThisExitPos];
17607 if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 0) || (NextEntryPos == 2)))
17609 BufferFlag =
false;
17614 BufferFlag =
false;
17619 BufferFlag =
false;
17627 else if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 1) || (NextEntryPos == 3)))
17629 ThisElement = NextElement;
17635 if(NextEntryPos == 0)
17639 else if(NextEntryPos == 1)
17643 else if(NextEntryPos == 2)
17647 else if(NextEntryPos == 3)
17652 ThisElement = NextElement;
17653 ThisExitPos = NextExitPos;
17658 if(BufferFacingUnReportedFlag)
17660 TTFile3 <<
"Train facing direction on creation analysis:-\n\n";
17661 BufferFacingUnReportedFlag =
false;
17663 TTFile3 <<
"Service " + TDE.
ServiceReference +
" facing buffers on creation\n";
17667 if(BufferFacingUnReportedFlag)
17669 TTFile3 <<
"Nothing to report for train facing directions\n\n";
17675 SequenceLog +=
"13c\n";
17678 AnsiString LocationNameToBeChecked =
"";
17679 bool MissingcdtUnreportedFlag =
true;
17681 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
17684 unsigned int y = 0;
17685 int FirstInstance = 9999, SecondInstance = 9999;
17686 bool FullBreak =
false;
17687 MarkerList.clear();
17694 while((y < TDEntry.
ActionVector.size()) && !FullBreak)
17703 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
17705 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
17710 (AVEntry.
Command ==
"Frh-sh"))
17725 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
17731 if(TDEntry.
ActionVector.at(a).LocationName == LocationNameToBeChecked)
17733 SecondInstance = a;
17735 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
17737 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
17739 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
17742 if(MissingcdtUnreportedFlag)
17744 TTFile3 <<
"Possibly missing changes of direction - these will be missing unless the service travels in a loop back to the locations marked:-\n\n";
17746 TTFile3 << LocationNameToBeChecked <<
" is listed twice with no direction change between in service sequence: " << Sequence <<
"\n\n";
17747 MarkerList.push_back(FirstInstance);
17748 MarkerList.push_back(SecondInstance);
17750 MissingcdtUnreportedFlag =
false;
17761 if(MissingcdtUnreportedFlag)
17763 TTFile3 <<
"Nothing to report for missing changes of direction\n\n";
17769 SequenceLog +=
"14\n";
17778 typedef std::list<AnsiString> TLocList;
17779 TLocList BackwardList, ForwardList;
17780 bool IntroLineNeeded =
true;
17781 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
17783 unsigned int cdtPosition = 9999;
17784 AnsiString cdtLocation =
"";
17785 bool FoundSameName =
false;
17786 MarkerList.clear();
17788 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
17791 BackwardList.clear();
17792 ForwardList.clear();
17796 (AVEntry.
Command ==
"Frh-sh"))
17798 if(MarkerList.empty())
17805 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
17807 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
17809 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
17813 if(IntroLineNeeded)
17815 TTFile3 <<
"Unexpected change of direction analysis.\n\n";
17816 TTFile3 <<
"For marked changes of direction there are no same-name locations listed both above and below.\n";
17817 TTFile3 <<
"These changes of direction are probably valid for movements to and from depots but all should be checked to\n";
17818 TTFile3 <<
"make sure that none has been included incorrectly:\n\n";
17819 IntroLineNeeded =
false;
17821 TTFile3 <<
"Service sequence " << Sequence <<
" contains unexpected changes of direction:-\n\n";
17833 for(
int z = y - 1; z >= 0; z--)
17836 if(AVEntry2.
Command ==
"cdt")
17845 BackwardList.sort();
17846 BackwardList.unique();
17847 for(
unsigned int z = y + 1; z < TDEntry.
ActionVector.size(); z++)
17861 ForwardList.sort();
17862 ForwardList.unique();
17863 FoundSameName =
false;
17865 if(!BackwardList.empty() && !ForwardList.empty())
17867 for(TLocList::iterator BLIt = BackwardList.begin(); BLIt != BackwardList.end(); BLIt++)
17869 for(TLocList::iterator FLIt = ForwardList.begin(); FLIt != ForwardList.end(); FLIt++)
17873 FoundSameName =
true;
17880 MarkerList.push_back(cdtPosition);
17884 if(IntroLineNeeded)
17886 TTFile3 <<
"Nothing to report for unexpected changes of direction\n\n";
17902 SequenceLog +=
"15\n";
17908 catch(
const Exception &e)
17910 AnsiString TTErrorFileName =
"Analysis Error.txt";
17911 TTErrorFileName = CurDir +
"\\Formatted timetables\\" + TTErrorFileName;
17912 std::ofstream TTError(TTErrorFileName.c_str());
17915 ShowMessage(
"Analysis error file failed to open - can't be created");
17919 AnsiString TimeNow = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17920 TTError << TimeNow.c_str() <<
'\n' << ArrRange <<
'\n' << ArrChecked <<
'\n' << DepRange <<
'\n' <<
17921 DepChecked <<
'\n' << AtLocChecked <<
'\n' << SequenceLog <<
'\n' << AnsiString(e.Message);
17924 ShowMessage(
"Error in Conflict Analysis: A file called 'Analysis Error.txt' has been created in your Formatted timetables folder. Please send this file together with your railway and timetable files to railwayfeedback@gmail.com for investigation - many thanks");
17934 if((SSVectorNumber < 0) || ((
unsigned int)SSVectorNumber >= SingleServiceVector.size()))
17936 throw Exception(
"SSVectorNumber out of range, = " + AnsiString(SSVectorNumber) +
", Vector size = " + SingleServiceVector.size());
17938 TTrainDataEntry SingleService = SingleServiceVector.at(SSVectorNumber);
17940 VecFile <<
",Initial service reference " << SingleService.
ServiceReference +
'\n';
17941 AnsiString Marker =
"";
17942 for(
unsigned int x = 0; x < SingleService.
ActionVector.size(); x++)
17945 for(
TNumListIterator MLIt = MarkerList.begin(); MLIt != MarkerList.end(); MLIt++)
17947 if(
int(x) == *MLIt)
17958 VecFile << Marker << AnsiString(AVE.
EventTime.TimeString()) <<
' ' << AVE.
Command <<
' ' << RearID <<
' ' << FrontID <<
'\n';
17964 VecFile << Marker << AnsiString(AVE.
EventTime.TimeString()) <<
' ' << AVE.
Command <<
' ' << RearID <<
' ' << FrontID <<
' ' << AVE.
OtherHeadCode <<
'\n';
17977 if(AVE.
Command.SubString(1,3) ==
"chr")
17986 AVE.
Command =
"Change of service to ";
17988 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"Fns-sh")
17990 AVE.
Command =
"Change to shuttle finishing service";
17992 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"F-nshs")
18015 VecFile << Marker << AnsiString(AVE.
EventTime.TimeString()) <<
' ' <<
"Pass" <<
' ' << AVE.
LocationName <<
'\n';
18019 AnsiString ListOfExits =
"";
18024 VecFile << Marker << AnsiString(AVE.
EventTime.TimeString()) <<
" Fer " << ListOfExits <<
'\n';
18028 VecFile << Marker <<
"Frh" <<
'\n';
18043 for(
unsigned int x = 0; x < Vector.size(); x++)
18047 if(Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1).FormatType ==
Repeat)
18049 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 2);
18052 FinishType =
false;
18057 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1);
18060 FinishType =
false;
18065 return(Vector.at(x));
18069 return(Vector.at(Vector.size() - 1));
18078 if((Time1 ==
"") || (Time2 ==
""))
18083 int Mins = Time1.SubString(4,2).ToInt();
18084 int Hours = Time1.SubString(1,2).ToInt();
18085 int Time1Mins = (Hours * 60) + Mins;
18086 Mins = Time2.SubString(4,2).ToInt();
18087 Hours = Time2.SubString(1,2).ToInt();
18088 int Time2Mins = (Hours * 60) + Mins;
18089 if(abs(Time1Mins - Time2Mins) <= MinuteRange)
18101 bool &AnalysisError,
int &MaxNumberOfSameDirections)
18108 AnsiString Output =
"", OneService =
"", TempStr1 =
"", TempStr2 =
"";
18110 std::list<AnsiString> ServiceList;
18112 bool EvenComma =
false;
18113 for(
int x = 1; x <= Input.Length(); x++)
18115 TempStr1 = Input[x];
18116 if(TempStr1 == AnsiString(
',') && EvenComma)
18122 TempStr2 += Input[x];
18124 if(TempStr1 == AnsiString(
','))
18126 EvenComma = !EvenComma;
18130 while(TempStr2.Length() > 0)
18132 SCPos = TempStr2.Pos(
';');
18135 OneService = TempStr2.SubString(1, SCPos - 1);
18136 ServiceList.push_back(OneService);
18137 TempStr2 = TempStr2.SubString(SCPos + 1, TempStr2.Length() - SCPos);
18141 ServiceList.push_back(TempStr2);
18145 ServiceList.sort();
18146 ServiceList.unique();
18147 NumTrainsAtLoc = ServiceList.size();
18150 int DirectionMarker = 0;
18152 std::list<AnsiString>::iterator SLIt, SLIt1, SLIt2, SLIt3;
18154 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
18156 *SLIt = *SLIt +
"&0";
18158 SLIt3 = ServiceList.end();
18160 AnsiString ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatInfo1, RepeatInfo2;
18161 int AmpersandPos, SpacePos, CommaPos1, CommaPos2, RepeatNum1, RepeatNum2;
18162 TAllServiceCallingLocsMap::iterator ASCLIt1, ASCLIt2;
18164 MaxNumberOfSameDirections = 0;
18165 int SameDirectionCount = 0;
18167 for(std::list<AnsiString>::iterator SLIt1 = ServiceList.begin(); SLIt1 != SLIt3; SLIt1++)
18171 if(SLIt1->SubString(SLIt1->Length() - 1, 2) != AnsiString(
"&0"))
18177 CommaPos1 = SLIt1->Pos(
',');
18178 ServiceRef1 = SLIt1->SubString(1, CommaPos1 - 1);
18180 SpacePos = ServiceRef1.Pos(
' ');
18184 RepeatInfo1 = ServiceRef1.SubString(SpacePos + 2, ServiceRef1.Length() - SpacePos - 2);
18185 ServiceRef1 = ServiceRef1.SubString(1, SpacePos - 1);
18186 if(RepeatInfo1[1] ==
'F')
18192 SpacePos = RepeatInfo1.Pos(
' ');
18193 RepeatNum1 = RepeatInfo1.SubString(SpacePos + 1, RepeatInfo1.Length() - SpacePos).ToInt();
18196 AnsiTime1 = SLIt1->SubString(CommaPos1 + 1, SLIt1->Length() - CommaPos1);
18198 AmpersandPos = AnsiTime1.Pos(
'&');
18199 AnsiTime1 = AnsiTime1.SubString(1, AmpersandPos - 1);
18204 throw Exception(
"ASCLIt1 Error in " + Input);
18206 ServiceCallingLocsList1 = ASCLIt1->second;
18207 AmpersandPos = SLIt1->Pos(
'&');
18208 *SLIt1 = SLIt1->SubString(1, AmpersandPos);
18209 *SLIt1 = *SLIt1 + AnsiString(++DirectionMarker);
18211 SameDirectionCount = 1;
18212 for(SLIt2 = SLIt; SLIt2 != ServiceList.end(); SLIt2++)
18214 CommaPos2 = SLIt2->Pos(
',');
18215 ServiceRef2 = SLIt2->SubString(1, CommaPos2 - 1);
18217 SpacePos = ServiceRef2.Pos(
' ');
18221 RepeatInfo2 = ServiceRef2.SubString(SpacePos + 2, ServiceRef2.Length() - SpacePos - 2);
18222 ServiceRef2 = ServiceRef2.SubString(1, SpacePos - 1);
18223 if(RepeatInfo2[1] ==
'F')
18229 SpacePos = RepeatInfo2.Pos(
' ');
18230 RepeatNum2 = RepeatInfo2.SubString(SpacePos + 1, RepeatInfo2.Length() - SpacePos).ToInt();
18233 AnsiTime2 = SLIt2->SubString(CommaPos2 + 1, SLIt2->Length() - CommaPos2);
18235 AmpersandPos = AnsiTime2.Pos(
'&');
18236 AnsiTime2 = AnsiTime2.SubString(1, AmpersandPos - 1);
18241 throw Exception(
"ASCLIt2 Error in " + Input);
18243 ServiceCallingLocsList2 = ASCLIt2->second;
18245 if(
SameDirection(0, ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatNum1, RepeatNum2, ServiceCallingLocsList1, ServiceCallingLocsList2, Location, Arrival))
18247 int AmpersandPos = SLIt2->Pos(
'&');
18248 *SLIt2 = SLIt2->SubString(1, AmpersandPos);
18249 *SLIt2 = *SLIt2 + AnsiString(DirectionMarker);
18250 SameDirectionCount++;
18253 if(SameDirectionCount > MaxNumberOfSameDirections)
18255 MaxNumberOfSameDirections = SameDirectionCount;
18260 if(SLIt3->SubString(SLIt3->Length() - 1, 2) == AnsiString(
"&0"))
18263 AmpersandPos = SLIt3->Pos(
'&');
18264 *SLIt3 = SLIt3->SubString(1, AmpersandPos);
18265 *SLIt3 = *SLIt3 + AnsiString(++DirectionMarker);
18268 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
18271 AmpersandPos = SLIt->Pos(
'&');
18272 AnsiString DirectionMarkerString = SLIt->SubString(AmpersandPos + 1, SLIt->Length() - AmpersandPos);
18273 AnsiString ServiceWithoutMarker = SLIt->SubString(1, AmpersandPos - 1);
18274 DirectionMarker = DirectionMarkerString.ToInt();
18275 AnsiString DirectionSuffix =
"";
18277 if(DirectionMarker < 27)
18279 c = 64 + DirectionMarker;
18280 DirectionSuffix =
"," + AnsiString(c);
18282 else if(DirectionMarker < 53)
18284 c = 65 + DirectionMarker - 27;
18285 DirectionSuffix =
",A" + AnsiString(c);
18289 DirectionSuffix =
",?";
18291 *SLIt = ServiceWithoutMarker + DirectionSuffix;
18294 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
18296 Output = Output + *SLIt +
",";
18298 if(Output.Length() > 0)
18300 Output = Output.SubString(1, Output.Length() - 1);
18306 catch(
const Exception &e)
18308 AnalysisError =
true;
18320 AnsiString InternalInput = Input, Output =
"", OneService =
"";
18322 std::list<AnsiString> ServiceList;
18324 while(InternalInput.Length() > 0)
18326 CommaPos = InternalInput.Pos(
',');
18329 OneService = InternalInput.SubString(1, CommaPos - 1);
18330 ServiceList.push_back(OneService);
18331 InternalInput = InternalInput.SubString(CommaPos + 1, InternalInput.Length() - CommaPos);
18335 ServiceList.push_back(InternalInput);
18336 InternalInput =
"";
18340 ServiceList.sort();
18341 ServiceList.unique();
18342 NumTrainsAtLoc = ServiceList.size();
18343 for(std::list<AnsiString>::iterator SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
18345 Output = Output + *SLIt +
",";
18347 if(Output.Length() > 0)
18349 Output = Output.SubString(1, Output.Length() - 1);
18362 AnsiString(RepeatNum1) +
"," + AnsiString(RepeatNum2) +
"," + Location);
18364 std::list<AnsiString>::iterator LP1 = 0, LP2 = 0, ListPtr1 = 0, ListPtr2 = 0, LocPtr1 = 0, LocPtr2 = 0;
18369 bool LocFound =
false;
18370 AnsiString Ref1 = Ref1In, Ref2 = Ref2In;
18372 TDateTime FirstServiceTime;
18375 int Ref1Target = 0, Ref1Count = 0;
18376 int SlashPos = Ref1.Pos(
'/');
18379 Ref1Target = Ref1.SubString(SlashPos + 1, Ref1.Length() - SlashPos).ToInt();
18380 Ref1 = Ref1.SubString(1, SlashPos - 1);
18382 int Ref2Target = 0, Ref2Count = 0;
18383 SlashPos = Ref2.Pos(
'/');
18386 Ref2Target = Ref2.SubString(SlashPos + 1, Ref2.Length() - SlashPos).ToInt();
18387 Ref2 = Ref2.SubString(1, SlashPos - 1);
18389 for(ListPtr1 = List1.begin(); ListPtr1 != List1.end(); ListPtr1++)
18392 if((*ListPtr1) == Location)
18394 LocPtr1 = ListPtr1;
18397 if(ListPtr1->SubString(1, 3) ==
"%%%")
18399 AnsiString CDTTime = ListPtr1->SubString(4, 5);
18404 FirstServiceTime = TDateTime(-1);
18405 bool BreakFlag =
false;
18408 if(TDVIt->ServiceReference == Ref1)
18410 if(Ref1Target > Ref1Count)
18415 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
18416 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
18420 FirstServiceTime = AVIt->EventTime;
18426 FirstServiceTime = AVIt->ArrivalTime;
18432 FirstServiceTime = AVIt->DepartureTime;
18443 if(IncMinutes == -1)
18445 throw Exception(
"Failed to find service for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
18447 if(FirstServiceTime == TDateTime(-1))
18449 throw Exception(
"Failed to find first service time for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
18453 if(!Arrival && (Time1 == CDTTime))
18458 if(Arrival && (Time1 == CDTTime))
18462 if(Time1 > CDTTime)
18467 if(Time1 < CDTTime)
18480 for(ListPtr2 = List2.begin(); ListPtr2 != List2.end(); ListPtr2++)
18482 if((*ListPtr2) == Location)
18484 LocPtr2 = ListPtr2;
18487 if(ListPtr2->SubString(1, 3) ==
"%%%")
18489 AnsiString CDTTime = ListPtr2->SubString(4, 5);
18494 FirstServiceTime = TDateTime(-1);
18495 bool BreakFlag =
false;
18498 if(TDVIt->ServiceReference == Ref2)
18500 if(Ref2Target > Ref2Count)
18505 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
18506 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
18510 FirstServiceTime = AVIt->EventTime;
18516 FirstServiceTime = AVIt->ArrivalTime;
18522 FirstServiceTime = AVIt->DepartureTime;
18533 if(IncMinutes == -1)
18535 throw Exception(
"IncMinutes -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
18537 if(FirstServiceTime == TDateTime(-1))
18539 throw Exception(
"First service time -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
18543 if(!Arrival && (Time2 == CDTTime))
18548 if(Arrival && (Time2 == CDTTime))
18552 if(Time2 > CDTTime)
18557 if(Time2 < CDTTime)
18572 LP1 = List1.begin();
18574 for(ListPtr1 = LocPtr1; ListPtr1 != LP1; ListPtr1--)
18576 if(ListPtr1 == List1.begin())
18580 if(ListPtr1->SubString(1, 3) ==
"%%%")
18587 LP2 = List2.begin();
18589 for(ListPtr2 = LocPtr2; ListPtr2 != LP2; ListPtr2--)
18591 if(ListPtr2 == List2.begin())
18595 if(ListPtr2->SubString(1, 3) ==
"%%%")
18605 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
18607 if(ListPtr1 == LocPtr1)
18611 if(ListPtr1->SubString(1, 3) ==
"%%%")
18615 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
18617 if(ListPtr2 == LocPtr2)
18621 if(ListPtr2->SubString(1, 3) ==
"%%%")
18625 if((*ListPtr1) == (*ListPtr2))
18642 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
18644 if(ListPtr1 == List1.end())
18648 if(ListPtr1->SubString(1, 3) ==
"%%%")
18652 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
18654 if(ListPtr2 == List2.end())
18658 if(ListPtr2->SubString(1, 3) ==
"%%%")
18662 if((*ListPtr1) == (*ListPtr2))
18679 if(ExitList.empty())
18685 AnsiString ExitLocList =
"";
18688 unsigned int Counter = 0;
18689 for(
TNumListIterator ELIt = ExitList.begin(); ELIt != ExitList.end(); ELIt++)
18693 if(((Counter % 6) == 0) && (Counter < (ExitList.size() - 1)))
18695 ExitLocList +=
"\n";
18698 if(StartName ==
"")
18700 if(ExitList.size() == 1)
18704 return(
" at " + ID);
18709 if(ExitList.size() < 4)
18711 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
18716 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
18721 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
18726 if(ExitList.size() < 4)
18728 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
18733 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
18739 if(ExitList.size() < 4)
18741 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
18742 return(
" at " + StartName);
18746 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
18747 return(
" at " + StartName);
18787 AnsiString FormatStr =
"####0.0";
18788 AnsiString AvLateArrMins =
"";
18789 AnsiString AvEarlyArrMins =
"";
18790 AnsiString AvLatePassMins =
"";
18791 AnsiString AvEarlyPassMins =
"";
18792 AnsiString AvLateDepMins =
"";
18793 AnsiString AvLateExitMins =
"";
18794 AnsiString AvEarlyExitMins =
"";
18824 PerfFile <<
'\n' <<
'\n' <<
"***************************************";
18825 PerfFile <<
'\n' <<
'\n' <<
"Performance summary:" <<
'\n';
18837 PerfFile <<
LateArrivals <<
" late arrivals (average " << AvLateArrMins.c_str() <<
" min)" <<
'\n';
18841 PerfFile <<
LateArrivals <<
" late arrival (" << AvLateArrMins.c_str() <<
" min)" <<
'\n';
18849 PerfFile <<
EarlyArrivals <<
" early arrivals (average " << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
18853 PerfFile <<
EarlyArrivals <<
" early arrival (" << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
18861 PerfFile <<
OnTimePasses <<
" on-time passes" <<
'\n';
18869 PerfFile <<
LatePasses <<
" late passes (average " << AvLatePassMins.c_str() <<
" min)" <<
'\n';
18873 PerfFile <<
LatePasses <<
" late pass (" << AvLatePassMins.c_str() <<
" min)" <<
'\n';
18877 PerfFile <<
LatePasses <<
" late passes" <<
'\n';
18881 PerfFile <<
EarlyPasses <<
" early passes (average " << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
18885 PerfFile <<
EarlyPasses <<
" early pass (" << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
18889 PerfFile <<
EarlyPasses <<
" early passes" <<
'\n';
18894 PerfFile <<
OnTimeExits <<
" on-time exits" <<
'\n';
18898 PerfFile <<
OnTimeExits <<
" on-time exit" <<
'\n';
18902 PerfFile <<
LateExits <<
" late exits (average " << AvLateExitMins.c_str() <<
" min)" <<
'\n';
18906 PerfFile <<
LateExits <<
" late exit (" << AvLateExitMins.c_str() <<
" min)" <<
'\n';
18910 PerfFile <<
LateExits <<
" late exits" <<
'\n';
18914 PerfFile <<
EarlyExits <<
" early exits (average " << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
18918 PerfFile <<
EarlyExits <<
" early exit (" << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
18922 PerfFile <<
EarlyExits <<
" early exits" <<
'\n';
18927 PerfFile <<
OnTimeDeps <<
" on-time departures" <<
'\n';
18931 PerfFile <<
OnTimeDeps <<
" on-time departure" <<
'\n';
18935 PerfFile <<
LateDeps <<
" late departures (average " << AvLateDepMins.c_str() <<
" min)" <<
'\n';
18939 PerfFile <<
LateDeps <<
" late departure (" << AvLateDepMins.c_str() <<
" min)" <<
'\n';
18943 PerfFile <<
LateDeps <<
" late departures" <<
'\n';
18945 TDateTime TempExcessLCDownTime;
18959 if(TempExcessLCDownTime > TDateTime(0))
18965 AnsiString FormattedExcessLCDownMins = FormatFloat(FormatStr,
ExcessLCDownMins);
18969 PerfFile << FormattedExcessLCDownMins.c_str() <<
" excess minutes of level crossing barrier down time" <<
'\n';
18973 PerfFile <<
MissedStops <<
" missed stops" <<
'\n';
18977 PerfFile <<
MissedStops <<
" missed stop" <<
'\n';
19005 PerfFile <<
NumFailures <<
" train failures" <<
'\n';
19009 PerfFile <<
NumFailures <<
" train failure" <<
'\n';
19015 PerfFile <<
AvHoursIntValue <<
" hour mean time betweeen train failures" <<
'\n';
19019 PerfFile <<
AvHoursIntValue <<
" hours mean time betweeen train failures" <<
'\n';
19022 AnsiString AvLateMinsLocsNotReached =
"";
19028 if(LocsNotReached > 0)
19031 PerfFile << LocsNotReached <<
" locations that trains failed to reach (average lateness " << AvLateMinsLocsNotReached.c_str() <<
" min)" <<
'\n';
19035 PerfFile <<
SPADRisks <<
" SPAD risks" <<
'\n';
19039 PerfFile <<
SPADRisks <<
" SPAD risk" <<
'\n';
19051 PerfFile <<
Derailments <<
" derailments" <<
'\n';
19055 PerfFile <<
Derailments <<
" derailment" <<
'\n';
19065 PerfFile <<
'\n' <<
"***************************************" <<
'\n';
19067 bool DerailSPADFlag =
false, CrashFlag =
false;
19069 int OverallScorePercent = 100;
19070 int TotArrDepExit = 0;
19071 double TotLateMinsFactor = 1;
19072 double MissedStopAndSPADRiskFactor = 1;
19073 double NetNegFactor = 1;
19083 OverallScorePercent = 5;
19084 DerailSPADFlag =
true;
19088 OverallScorePercent = 0;
19091 if(OverallScorePercent == 100)
19093 if(TotArrDepExit > 0)
19095 TotLateMinsFactor =
19103 NetNegFactor = TotLateMinsFactor * MissedStopAndSPADRiskFactor;
19105 OverallScorePercent = 100 * NetNegFactor;
19108 if((TotArrDepExit > 0) || DerailSPADFlag || CrashFlag)
19111 AnsiString OneFailureString =
", though the failure would account for some poor performance";
19112 AnsiString TwoOrMoreFailureString =
", though the failures would account for some poor performance";
19113 AnsiString AddedString =
"";
19116 AddedString = OneFailureString;
19120 AddedString = TwoOrMoreFailureString;
19122 PerfFile <<
"\nOverall score: " << OverallScorePercent <<
"%\n";
19123 AnsiString Rating =
"";
19124 if(OverallScorePercent == 100)
19126 Rating =
"Perfect!";
19128 else if(OverallScorePercent >= 95)
19130 Rating =
"Excellent";
19132 else if(OverallScorePercent >= 90)
19134 Rating =
"Very good";
19136 else if(OverallScorePercent >= 80)
19140 else if(OverallScorePercent >= 70)
19144 else if(OverallScorePercent >= 60)
19146 Rating =
"Unacceptable" + AddedString;
19148 else if(OverallScorePercent >= 50)
19150 Rating =
"Poor" + AddedString;
19152 else if(OverallScorePercent >= 40)
19154 Rating =
"Bad" + AddedString;
19156 else if(OverallScorePercent >= 30)
19158 Rating =
"Very bad" + AddedString;
19160 else if(OverallScorePercent >= 20)
19162 Rating =
"Terrible" + AddedString;
19164 else if(OverallScorePercent >= 10)
19166 Rating =
"Appalling" + AddedString;
19168 else if(OverallScorePercent >= 5)
19172 Rating =
"Disastrous - potential loss of life";
19177 Rating =
"Dire" + AddedString;
19180 else if(OverallScorePercent < 5)
19184 Rating =
"Catastrophic - loss of life";
19188 Rating =
"Abysmal";
19191 PerfFile <<
"Overall rating: " << Rating.c_str() <<
'\n';
19195 PerfFile <<
"\nThere were no timetabled departures, arrivals or exits so there is insufficient information to provide a performance score or rating" <<
'\n';
19197 PerfFile <<
'\n' <<
"***************************************";
19206 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
19256 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
19291 int IncrementalMinutes = 0;
19305 bool TrainOperatingFlag =
false;
19310 TrainOperatingFlag =
true;
19314 if(TrainOperatingFlag)
19322 for(
unsigned int z = 0; z < TDEntry.
ActionVector.size(); z++)
19369 AnsiString HeadCode;
19373 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
19377 HCandTrainPosParam.first = HeadCode;
19378 HCandTrainPosParam.second = TrainID;
19380 if((TimeToAct >= 0) && (TimeToAct < 59.9))
19383 OpTimeToActMultiMapEntry.first = TimeToAct;
19384 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
19413 float TimeToAct = 0;
19414 int DistanceToRedSignal = 0;
19417 ContinuationEntryVecPosVector.clear();
19418 bool LaterTrain =
false;
19422 LaterTrain =
false;
19423 if(CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)
19434 if(!ContinuationEntryVecPosVector.empty())
19436 for(
unsigned int x = 0; x < ContinuationEntryVecPosVector.size(); x++)
19438 if(CTEIt->second.VectorPosition == ContinuationEntryVecPosVector.at(x))
19452 ContinuationEntryVecPosVector.push_back(CTEIt->second.VectorPosition);
19453 AnsiString HeadCode = CTEIt->second.HeadCode;
19454 float CurrentStopTime;
19455 float LaterStopTime;
19456 float RecoverableTime;
19459 bool SigControlAndCanPassRedSignal =
false;
19463 SigControlAndCanPassRedSignal, &CTEIt->second.TrainDataEntryPtr->ActionVector.at(1),
19465 HeadCode, TrainID, CurrentStopTime, LaterStopTime, RecoverableTime, AvTrackSpeed);
19468 if(AvTrackSpeed < 30)
19472 if(DistanceToRedSignal == -1)
19478 int Speed = AvTrackSpeed;
19479 int MaxSpeed = int(CTEIt->second.TrainDataEntryPtr->MaxRunningSpeed);
19480 if(AvTrackSpeed > MaxSpeed)
19484 if(CTEIt->second.TrainDataEntryPtr->ActionVector.at(1).SignallerControl)
19487 Speed = CTEIt->second.TrainDataEntryPtr->SignallerSpeed;
19490 TimeToAct = LaterStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
19495 float MinsBefEnter = double(CTEIt->first -
TTClockTime) * 86400.0 / 60.0;
19496 TimeToAct += MinsBefEnter;
19499 HCandTrainPosParam.first = HeadCode;
19500 HCandTrainPosParam.second = -1 - CTEIt->second.VectorPosition;
19503 if(TimeToAct < 59.9)
19505 OpTimeToActMultiMapEntry.first = TimeToAct;
19506 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
19518 bool SigControlAndCanPassRedSignal,
TActionVectorEntry *AVPtr, AnsiString HeadCode,
int TrainID,
float &CurrentStopTime,
float &LaterStopTime,
19519 float &RecoverableTime,
int &AvTrackSpeed)
19528 AnsiString(TrackVectorPositionEntryPos) +
", " + AVPtr->
Command);
19529 int DistanceToRedSignal = 0;
19530 int CumTrackSpeed = 0;
19532 int TrackSpeedCount = 0;
19542 int CurrentElement = TrackVectorPosition;
19543 int CurrentEntryPos = TrackVectorPositionEntryPos;
19548 CurrentStopTime = 0;
19550 RecoverableTime = 0;
19551 if(CurrentElement == -1)
19556 int CurrentExitPos;
19561 if((CurrentEntryPos == 0) || (CurrentEntryPos == 2))
19565 CurrentExitPos = 1;
19569 CurrentExitPos = 3;
19574 CurrentExitPos = 0;
19610 CurrentStopTime = float(TimeToDepart);
19616 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
19627 else if(SigControlAndCanPassRedSignal)
19632 if((NextEntryPos == 0) || (NextEntryPos == 2))
19653 CurrentElement = NextElement;
19654 CurrentEntryPos = NextEntryPos;
19655 CurrentExitPos = NextExitPos;
19667 int LaterStopNumber = 0;
19671 while(!((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0)))
19680 if(CurrentEntryPos > 1)
19700 bool StopRequired =
false;
19717 int TrainOnElement;
19724 if(CurrentEntryPos > 1)
19733 if((TrainOnElement > -1) && (TrainOnElement != TrainID))
19742 double StopTimeDouble;
19755 if(StopTimeDouble < 0.5)
19757 StopTimeDouble = 0.5;
19761 LaterStopTime += float(StopTimeDouble);
19762 RecoverableTime += StopTimeDouble - 0.5;
19763 if((LaterStopNumber == 1) && (TrainID > -1))
19771 if((AVPtr + 1)->FormatType ==
TimeLoc)
19775 StopTimeDouble = double((AVPtr + 1)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
19777 if(StopTimeDouble < 0.5)
19779 StopTimeDouble = 0.5;
19782 LaterStopTime += float(StopTimeDouble);
19783 RecoverableTime += StopTimeDouble - 0.5;
19784 if((LaterStopNumber == 1) && (TrainID > -1))
19800 if(NextElement == -1)
19809 if((NextEntryPos == 0) || (NextEntryPos == 2))
19830 CurrentElement = NextElement;
19831 CurrentEntryPos = NextEntryPos;
19832 CurrentExitPos = NextExitPos;
19836 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
19851 float MaxAllowableSpeed;
19853 if(TrackSpeedCount > 0)
19855 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
19859 if(CurrentEntryPos > 1)
19869 float KmPerLocationStop;
19871 if(LaterStopNumber > 0)
19873 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
19874 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
19878 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
19882 if(AvTrackSpeed > MaxAllowableSpeed)
19884 AvTrackSpeed = MaxAllowableSpeed;
19887 return(DistanceToRedSignal);